Introduction
Bienvenue sur la documentation de l'API Pro Capfile. Cette interface REST permet d'interroger les données brutes de soutirage (consommation) et d'injection (production) d'un point de livraison.
Aucune information tarifaire n'est renvoyée par cette API (pas de prix, d'abonnement ni de puissance souscrite) : elle expose les données techniques et énergétiques brutes du compteur, à charge pour l'intégrateur d'appliquer sa propre logique métier.
Toutes les réponses sont en JSON et partagent la même enveloppe { success, code, message, data }. En cas d'erreur, le statut HTTP de la réponse reprend la valeur de code (voir codes d'erreur).
Authentification
Deux modes d'authentification sont disponibles selon l'action effectuée :
- Basic Auth : Obligatoire pour la gestion de la clé. Format
Authorization: Basic Base64(login:password). - API Key Auth : Recommandé pour l'accès aux données. En-tête :
x-api-key: VOTRE_CLE_API.
Gestion de la Clé API
Endpoints accessibles uniquement via Basic Auth.
Récupère la clé API active associée à votre compte.
{
"success": true,
"code": 200,
"message": "Clé API",
"data": {
"api_key": "TamxBsK9hTjszezcSy4sdfsdfsdfqRmYUFo"
}
}
Révoque la clé actuelle et en génère une nouvelle immédiatement.
{
"success": true,
"code": 200,
"message": "Clé API renouvelée",
"data": {
"api_key": "anQBz1brst89eymswVCqhk29mpKqnb7n"
}
}
Compteurs
Récupère la liste de tous les compteurs accessibles avec la clé API fournie, y compris les compteurs partagés par d'autres utilisateurs Capfile.
Cet endpoint requiert l'authentification par API Key (x-api-key).
Réponse JSON
{
"success": true,
"code": 200,
"message": "OK",
"data": [
{
"prm": "12345678901234",
"name": "Maison principale"
},
{
"prm": "98765432109876",
"name": "Appartement voisin",
"shared": true
}
]
}
prm: Identifiant du point de livraison (14 chiffres).name: Nom du site associé au compteur.shared: Présent et àtrueuniquement si le compteur appartient à un autre utilisateur Capfile et vous a été partagé. Ce champ est absent pour vos propres compteurs.
Un même compte peut avoir accès à des compteurs appartenant à d'autres utilisateurs Capfile. Pour ces compteurs (shared: true), l'accès aux endpoints /info, /index et /loadcurve dépend des options de partage définies par le propriétaire du compteur.
Infos Compteur
Récupère les informations techniques brutes d'un PRM : segments contractuels en service, informations techniques (ITC), et grandeurs physiques disponibles en soutirage et en injection. Aucune donnée tarifaire n'est renvoyée par cet endpoint.
Cet endpoint requiert l'authentification par API Key (x-api-key).
Réponse JSON (extrait, "itc" tronqué)
{
"success": true,
"code": 200,
"message": "OK",
"data": {
"prm": "12345678901234",
"name": "Maison principale",
"segments": {
"C5": {
"segment": "C5",
"etatContractuel": "En service",
"etatContractuelCode": "SERVC"
}
},
"itc": {
"point": {
"donneesGenerales": { "...": "..." },
"situationContractuelle": { "...": "..." }
}
},
"soutirage": {
"grandeurs_physiques": {
"EA": "Energie Active (Wh)"
},
"itc": { "...": "informations techniques spécifiques au flux de soutirage" }
},
"injection": {
"grandeurs_physiques": {
"EA": "Energie Active (Wh)"
},
"itc": { "...": "informations techniques spécifiques au flux d'injection" },
"puissance_raccordement": 12.0
}
}
}
segments: Dictionnaire des segments contractuels connus pour ce PRM, avec leur état contractuel.itc: Informations Techniques et Contractuelles du point de livraison. Structure riche et variable selon le compteur.
grandeurs_physiques: Dictionnairecode → libellédes grandeurs physiques mesurées et disponibles pour ce flux (ex.EA= Energie Active). La liste dépend du compteur — voir la table des grandeurs physiques.itc: Informations techniques spécifiques au flux (injection ou soutirage).puissance_raccordement(injection uniquement) : Puissance de raccordement en kVA,0si non disponible.
Le bloc soutirage est absent si le PRM ne soutire pas ; le bloc injection est absent si le PRM n'injecte pas.
Données d'Index
Récupère l'historique des index quotidiens pour une grandeur physique donnée. Cet endpoint requiert l'authentification par API Key (x-api-key).
Même convention pour tous les compteurs, Linky ou télérelevés : la ligne datée D porte l'index relevé à la fin de la journée D (cadran_*) et l'énergie de la journée D (différence avec la veille). Un seul relevé par jour est retenu, le premier après minuit ; pour un compteur télérelevé il a lieu quelques minutes après minuit.
Définit le flux :
sou: Soutirage (consommation)inj: Injection (production)
Code de la grandeur physique à récupérer (ex. EA, ER…). Les valeurs possibles dépendent du compteur : consultez le champ grandeurs_physiques renvoyé par /data/{PRM}/info pour ce PRM, dans le bloc soutirage ou injection correspondant. Une valeur non disponible pour ce compteur renvoie une erreur 400.
Différence vs Réel
Les champs sont doublés dans chaque ligne de data :
- NOM_CADRAN : Différence par rapport à la veille (valeur "journalière"), dans l'unité de la grandeur physique (ex. Wh pour EA).
- cadran_NOM_CADRAN : Index cumulé lu sur le compteur à minuit.
Réponse JSON
{
"success": true,
"code": 200,
"message": "OK",
"data": {
"head": {
"prm": "12345678901234",
"type": "index",
"sens": "sou",
"grandeur_physique": "EA",
"start_date": "2026-03-04",
"end_date": "2026-03-11"
},
"data": [
{
"date": "2026-03-04",
"BASE": "11593",
"Total": "11593",
"cadran_BASE": "17539897",
"cadran_Total": "17539897"
},
{
"date": "2026-03-05",
"BASE": "11021",
"Total": "11021",
"cadran_BASE": "17550918",
"cadran_Total": "17550918"
}
]
}
}
Le nombre et le nom des champs (autres que date et Total) dépendent des cadrans réellement utilisés par le compteur pour la grandeur physique demandée.
Courbe de Charge
Données précises au pas défini par le compteur (énergie active uniquement). Unité : Wh (numérique). Chaque point est horodaté à la fin de son intervalle, en heure légale française avec décalage explicite (voir Horodatage ci-dessous).
Définit le flux :
sou: Soutirage (consommation)inj: Injection (production)
date_time
ISO 8601 avec décalage explicite : 2026-03-01T00:30:00+01:00. L'heure affichée est l'heure légale française (head.timezone = Europe/Paris), le décalage vaut +01:00 en hiver et +02:00 en été ; l'instant est donc exact et directement exploitable par tout parseur de dates (new Date(), DateTime, datetime.fromisoformat…).
- Le point est horodaté à la fin de son intervalle de mesure (convention Enedis) :
2026-03-01T00:30:00+01:00avecp = 30couvre 00:00 → 00:30. start_date/end_datesont des jours civils français.- Dernier dimanche de mars : la journée compte 23 heures de données (pas de point entre 02:00 et 02:59, heure inexistante).
- Dernier dimanche d'octobre : la journée compte 24 heures de données pour 25 heures réelles ; les points
02:xxrenvoyés sont ceux de l'heure d'hiver (+01:00).
Le champ p indique la durée de l'intervalle de mesure en minutes. Il est porté par chaque point et peut changer au cours de l'historique d'un même compteur (Enedis modifie le pas de collecte, ou comble certains jours à un pas plus grossier) : utilisez toujours le p du point, jamais une valeur supposée constante. Les valeurs possibles sont :
5minutes10minutes15minutes30minutes60minutes
Réponse JSON
{
"success": true,
"code": 200,
"message": "OK",
"data": {
"head": {
"prm": "04389580265458",
"type": "loadcurve",
"sens": "sou",
"timezone": "Europe/Paris",
"start_date": "2026-03-01",
"end_date": "2026-03-11"
},
"data": [
{
"date_time": "2026-03-01T00:30:00+01:00",
"p": 30,
"Wh": 81
},
{
"date_time": "2026-03-01T01:00:00+01:00",
"p": 30,
"Wh": 92
},
{
"date_time": "2026-03-01T01:30:00+01:00",
"p": 30,
"Wh": 81
}
]
}
}
Gestion des Quotas
L'utilisation de l'API est encadrée par des quotas fixes basés sur le calendrier (et non glissants) :
- Quotas quotidiens : Se réinitialisent chaque jour à 00:00.
- Quotas hebdomadaires : Basés sur la semaine calendaire, du Lundi au Dimanche.
- Quotas mensuels : Basés sur le mois calendaire en cours.
Le dépassement de l'une de ces limites entraîne une erreur 429. Les compteurs sont remis à zéro au début de chaque nouvelle période (jour, lundi ou 1er du mois).
Consulte vos quotas autorisés, votre consommation actuelle et le nombre d'appels restants sur chaque période. Cet endpoint requiert l'authentification par API Key (x-api-key) et n'est pas soumis lui-même au décompte des quotas.
Réponse JSON
{
"success": true,
"code": 200,
"message": "Usage et quotas",
"data": {
"quotas": {
"day": 5000,
"week": 50000,
"month": 300000
},
"usage": {
"day": 120,
"week": 890,
"month": 3400
},
"remaining": {
"day": 4880,
"week": 49110,
"month": 296600
}
}
}
quotas: Limites autorisées pour votre compte, par période.usage: Nombre d'appels déjà effectués sur la période en cours (jour, semaine calendaire, mois calendaire).remaining: Nombre d'appels restants avant d'atteindre chaque quota (jamais négatif).
Table des grandeurs physiques
Codes utilisables pour le paramètre {GP} de l'endpoint /index. La disponibilité réelle par PRM est donnée par grandeurs_physiques dans /info.
EA: Energie Active (Wh)ER: Energie Réactive (VARh)ERI: Energie Réactive Inductive (VARh)ERC: Energie Réactive Capacitive (VARh)PMA: Puissance Maximale (VA)TF: Temps de Fonctionnement (s)DD: Durée de Dépassement (s)DE: Dépassement Energétique (s)DQ: Dépassement Quadratique (W)
Webhook : notification d'arrivée de données
Plutôt que d'interroger l'API en boucle, vous pouvez enregistrer une URL que Capfile appelle dès que de nouvelles données sont disponibles pour l'un des compteurs listés par /meters (vos compteurs et ceux partagés avec vous). La notification vous indique le compteur, le type de données et la période concernée : à vous ensuite d'aller chercher les données via /info, /index ou /loadcurve.
Les endpoints de configuration ci-dessous acceptent l'authentification par API Key ou Basic Auth et sont soumis aux quotas.
Renvoie la configuration actuelle de votre webhook.
Réponse JSON
{
"success": true,
"code": 200,
"message": "Configuration du webhook",
"data": {
"url": "https://www.monsite.fr/capfile/webhook",
"secret": "3f9c…",
"ssl_verify_peer": true,
"ssl_verify_host": true,
"configured": true
}
}
url: URL appelée en POST à chaque notification.secret: clé partagée servant à signer les notifications (voir Signature ci-dessous).ssl_verify_peer/ssl_verify_host: vérification du certificat TLS de votre serveur (à laisser àtrueen production).configured:truequandurletsecretsont renseignés, c'est-à-dire quand les notifications sont actives.
Enregistre ou modifie la configuration (PUT accepté). Corps JSON, tous les champs sont optionnels sauf url lors de la première configuration ; les champs absents conservent leur valeur.
{
"url": "https://www.monsite.fr/capfile/webhook",
"secret": "une-cle-secrete-de-16-caracteres-minimum",
"ssl_verify_peer": true,
"ssl_verify_host": true
}
url: absolue, enhttps(ouhttp), vers un hôte public. Les adresses locales ou privées sont refusées.secret: 16 caractères minimum. S'il est omis à la première configuration, un secret aléatoire est généré et renvoyé dans la réponse.- La réponse contient la configuration enregistrée (même format que
GET /webhook).
400: URL manquante ou invalide, secret trop court.
Supprime la configuration et arrête les notifications (POST /webhook/delete accepté si votre client HTTP ne gère pas DELETE).
Provoque immédiatement un appel de votre webhook avec une notification d'exemple, pour valider votre intégration. Le corps JSON est optionnel :
{
"prm": "12345678901234", // défaut : votre premier compteur
"type": "loadcurve", // info | index | loadcurve (défaut : loadcurve)
"start_date": "2026-10-01", // défaut : il y a 7 jours
"end_date": "2026-10-07" // défaut : aujourd'hui
}
La notification envoyée est identique à une notification réelle, avec en plus le champ "test": true. La réponse décrit le résultat de l'appel :
{
"success": true,
"code": 200,
"message": "Webhook appelé",
"data": {
"status": "OK",
"http_code": 200,
"duration_ms": 143,
"response": "…corps renvoyé par votre serveur (2000 premiers caractères)…",
"payload": { "hook": "data_updated", "prm": "12345678901234", "name": "Bureau", "type": "loadcurve", "start_date": "2026-10-01", "end_date": "2026-10-07", "test": true },
"signature": "a3c1…"
}
}
400: webhook non configuré, type ou dates invalides, aucun compteur disponible.403: PRM demandé non accessible depuis votre compte.502: votre serveur n'a pas répondu en 2xx (success: false) ;statusetresponsedonnent le détail.
La notification reçue par votre serveur
Requête POST, en-tête Content-Type: application/json, corps JSON :
{
"hook": "data_updated",
"prm": "12345678901234",
"name": "Bureau",
"type": "loadcurve",
"start_date": "2026-10-01",
"end_date": "2026-10-07"
}
hook: type d'événement, toujoursdata_updated.prm/name: compteur concerné (numéro de PRM et nom donné dans Capfile).type: nature des données arrivées :info(caractéristiques techniques),index(index quotidiens) ouloadcurve(courbe de charge).start_date/end_date: période couverte par les données reçues (absents pourinfo).test: présent et àtrueuniquement pour les appels déclenchés par/webhook/test.
- Votre serveur doit répondre en 2xx dans les 10 secondes (5 s pour établir la connexion). Toute autre réponse est considérée comme un échec.
- Pas de nouvelle tentative automatique : une notification manquée n'est pas renvoyée. Les données restent bien sûr disponibles via l'API.
- Le sens (soutirage/injection) et les grandeurs physiques ne sont pas précisés : interrogez
/indexet/loadcurvepour les flux qui vous intéressent, avec la période indiquée. - Un même import peut générer plusieurs notifications (une par type de données).
Signature
Chaque notification porte un en-tête X-Signature contenant le HMAC-SHA256 (hexadécimal) du corps brut de la requête, calculé avec votre secret. Vérifiez-la avant tout traitement : c'est la garantie que la requête vient bien de Capfile et n'a pas été altérée.
<?php
// Réception d'une notification Capfile (exemple PHP)
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); exit; }
$secret = 'votre-secret'; // celui renvoyé par GET /webhook
$rawBody = file_get_contents('php://input'); // corps brut, avant tout décodage
$expected = hash_hmac('sha256', $rawBody, $secret);
$received = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
if (!hash_equals($expected, $received)) { http_response_code(401); exit('Signature invalide'); }
$event = json_decode($rawBody, true);
if (!is_array($event) || ($event['hook'] ?? '') !== 'data_updated') { http_response_code(400); exit; }
http_response_code(200); // répondre vite : le traitement lourd peut se faire ensuite
// … par exemple : mettre en file d'attente un appel à
// GET /data/{$event['prm']}/{$event['type']}/… pour la période start_date → end_date
Codes d'erreur détaillés
En cas d'erreur, la réponse JSON a success: false et un code qui est aussi le statut HTTP de la réponse ; message précise la cause.
La requête contient des erreurs de syntaxe ou des paramètres manquants/invalides. Causes possibles :
- PRM mal formé (doit faire exactement 14 chiffres).
{SENS}manquant ou différent desou/inj.{GP}manquant ou non disponible pour ce compteur (voirgrandeurs_physiquesdans/info).- Format de date invalide (le format attendu est YYYY-MM-DD) ou dates incohérentes.
- Webhook : URL manquante ou invalide, secret trop court, webhook non configuré pour un test.
Identifiants Basic Auth incorrects ou clé API x-api-key non reconnue.
Compte non pro, compteur non accessible depuis votre compte (ni à vous, ni partagé avec les droits nécessaires), ou période demandée au-delà de l'historique autorisé (3 ans pour /index, 1 an pour /loadcurve).
Endpoint inconnu.
Un des quotas (journalier, hebdomadaire ou mensuel) a été atteint. L'en-tête Retry-After et le champ retry_after_seconds indiquent le délai avant le prochain appel possible.
/webhook/test uniquement : votre serveur n'a pas répondu en 2xx (ou pas répondu du tout) ; le détail est dans data.status et data.response.
Erreur inattendue côté Capfile. Réessayez plus tard ; si l'erreur persiste, contactez-nous avec l'URL appelée et l'heure de l'appel.