Retour au blog
APIdéveloppementguide techniquetutoriel

Comment utiliser l'API DVF : Guide développeur complet

IM

Immo API

·12 min de lecture
Comment utiliser l'API DVF : Guide développeur complet

Premiers pas avec Immo API

Ce guide vous accompagne dans l'intégration d'Immo API dans vos projets. Que vous développiez une application web, mobile ou un script d'analyse de données, vous trouverez ici toutes les informations nécessaires pour démarrer rapidement.

Si vous n'êtes pas encore familier avec les données DVF, nous vous recommandons de lire d'abord notre article Qu'est-ce que le DVF ? pour comprendre la structure et le contenu des données.

Avant de plonger dans le code, la vidéo ci-dessous illustre concrètement à quoi servent ces données une fois interrogées : estimer un bien, comparer des transactions récentes, lire un prix médian. C'est exactement le type de résultat que votre intégration produira à partir des endpoints décrits plus bas.

Architecture de l'API

Immo API est une API REST qui retourne des réponses au format JSON. Elle est accessible via HTTPS et nécessite une authentification par Bearer token pour toutes les requêtes. Vous obtenez votre clé API en créant un compte sur immoapi.app ; elle est disponible immédiatement dans votre tableau de bord.

URL de base

https://immoapi.app/v1

Authentification

Chaque requête doit inclure un header Authorization avec votre clé API au format Bearer token :

Authorization: Bearer YOUR_API_KEY

Si le header est absent ou si la clé est invalide, l'API retourne une erreur 401. Pensez à stocker votre clé dans une variable d'environnement plutôt que de la coder en dur dans votre code source, notamment si vous utilisez un dépôt Git public.

Format des réponses

Toutes les réponses de l'endpoint /v1/mutations suivent une structure cohérente :

{
  "total": 150,
  "mutations": [...],
  "page": 1,
  "per_page": 20
}

Le champ total indique le nombre total de résultats correspondant à vos filtres. Le tableau mutations contient les transactions de la page courante. Les champs page et per_page reflètent les paramètres de pagination utilisés. Pour connaître le nombre total de pages, divisez total par per_page (arrondi au supérieur).

Plans et limites

Immo API propose deux plans tarifaires :

  • Starter (29 euros/mois) : 1 000 requêtes par jour. Idéal pour les phases de développement et les applications à trafic modéré
  • Pro (49 euros/mois) : requêtes illimitées. Conçu pour les applications en production à fort trafic

Les headers de réponse incluent X-RateLimit-Remaining et X-RateLimit-Reset pour suivre votre consommation en temps réel.

Endpoints principaux

Recherche de mutations

L'endpoint principal permet de rechercher des mutations (transactions) avec de nombreux filtres :

GET /v1/mutations?code_commune=75056&annee=2024

Paramètres de filtrage

  • code_commune : code INSEE de la commune (ex : 75056 pour Paris, 69123 pour Lyon, 13055 pour Marseille)
  • code_departement : code du département (ex : 75, 69, 13)
  • type_local : type de bien (Appartement, Maison, Local industriel, Dépendance)
  • annee : année de la transaction (ex : 2024)
  • prix_min / prix_max : fourchette de prix en euros
  • surface_min / surface_max : fourchette de surface en m2
  • page : numéro de page (défaut : 1)
  • per_page : résultats par page, max 100 (défaut : 20)

Vous devez fournir au moins un filtre géographique (code_commune ou code_departement) pour que la requête soit valide. Les filtres sont combinés avec un opérateur ET : par exemple, code_departement=75&type_local=Appartement&prix_min=200000 retourne uniquement les appartements à Paris vendus à plus de 200 000 euros.

Recherche par proximité

L'endpoint /v1/mutations/nearby permet de trouver les transactions à proximité d'un point géographique :

GET /v1/mutations/nearby?lat=48.8566&lng=2.3522&radius=500&type_local=Appartement

Les paramètres lat et lng sont requis. Le paramètre radius définit le rayon de recherche en mètres (défaut : 1 000, max : 5 000). Chaque résultat inclut un champ distance_m indiquant la distance en mètres par rapport au point central.

Statistiques agrégées

L'endpoint /v1/stats fournit des statistiques prêtes à l'emploi :

GET /v1/stats?code_departement=75&annee=2024&type_local=Appartement

La réponse inclut le nombre de transactions, le prix médian et moyen au m2, la surface moyenne, la valeur foncière médiane, l'évolution annuelle en pourcentage, la répartition par nombre de pièces et les prix au m2 par trimestre.

Exemples de code

JavaScript / TypeScript (fetch)

const API_KEY = process.env.IMMO_API_KEY;

async function getMutations(codeCommune: string, annee: number) {
  const params = new URLSearchParams({
    code_commune: codeCommune,
    annee: String(annee),
    per_page: '50'
  });

  const response = await fetch(
    `https://immoapi.app/v1/mutations?${params}`,
    {
      headers: {
        'Authorization': `Bearer ${API_KEY}`
      }
    }
  );

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  const result = await response.json();
  return result.mutations;
}

// Exemple : transactions à Paris en 2024
const transactions = await getMutations('75056', 2024);
console.log(`Nombre de transactions : ${transactions.length}`);

Python (requests)

import os
import requests

API_KEY = os.environ['IMMO_API_KEY']

def get_mutations(code_commune, annee):
    params = {
        'code_commune': code_commune,
        'annee': annee,
        'per_page': 50
    }
    response = requests.get(
        'https://immoapi.app/v1/mutations',
        params=params,
        headers={'Authorization': f'Bearer {API_KEY}'}
    )
    response.raise_for_status()
    return response.json()['mutations']

# Exemple : transactions à Lyon en 2024
transactions = get_mutations('69123', 2024)
print(f'Nombre de transactions : {len(transactions)}')

cURL

curl "https://immoapi.app/v1/mutations?code_departement=75&type_local=Appartement&annee=2024&per_page=10" \
  -H "Authorization: Bearer YOUR_API_KEY"

Astuce : pour un affichage formaté en local, ajoutez | python3 -m json.tool (ou | jq . si vous avez jq installé) à la fin de la commande cURL.

Gestion de la pagination

Pour les requêtes retournant de nombreux résultats, l'API utilise un système de pagination. Le nombre total de résultats est indiqué dans le champ total de la réponse. Voici comment parcourir toutes les pages :

const API_KEY = process.env.IMMO_API_KEY;

async function getAllMutations(codeCommune: string) {
  let allMutations = [];
  let page = 1;
  const perPage = 100;
  let totalPages = 1;

  while (page <= totalPages) {
    const params = new URLSearchParams({
      code_commune: codeCommune,
      page: String(page),
      per_page: String(perPage)
    });

    const response = await fetch(
      `https://immoapi.app/v1/mutations?${params}`,
      {
        headers: {
          'Authorization': `Bearer ${API_KEY}`
        }
      }
    );
    const result = await response.json();

    allMutations = [...allMutations, ...result.mutations];
    totalPages = Math.ceil(result.total / perPage);
    page++;
  }

  return allMutations;
}

Attention : si vous parcourez toutes les pages d'un département complet, le nombre de requêtes peut être important. Avec le plan Starter (1 000 requêtes/jour), pensez à mettre en cache les résultats pour éviter de dépasser votre quota. Les données DVF ne changent que deux fois par an, donc un cache de 24 heures est parfaitement raisonnable.

Bonnes pratiques

Sécuriser votre clé API

  • Variables d'environnement : stockez votre clé dans IMMO_API_KEY plutôt que dans le code source
  • Côté serveur uniquement : n'exposez jamais votre clé dans du code JavaScript côté client (navigateur). Utilisez un backend ou une fonction serverless comme intermédiaire
  • Rotation : si votre clé est compromise, vous pouvez en générer une nouvelle depuis votre tableau de bord

Optimiser vos requêtes

  • Utilisez des filtres précis : plus vos filtres sont précis, plus la réponse sera rapide. Préférez code_commune à code_departement quand c'est possible
  • Limitez la taille des pages : ne demandez que le nombre de résultats dont vous avez besoin via le paramètre per_page
  • Cachez les résultats : les données DVF ne changent que deux fois par an (avril et octobre), mettez en cache les réponses pour réduire votre consommation
  • Utilisez /v1/stats pour les agrégats : plutôt que de récupérer toutes les transactions pour calculer une moyenne, utilisez l'endpoint de statistiques qui fait le calcul côté serveur
  • Gérez les erreurs : implémentez un mécanisme de retry avec backoff exponentiel pour les erreurs 429 (rate limit) et 500 (erreur serveur)

Gestion des erreurs

Voici un wrapper robuste qui gère les retries et les différents codes d'erreur :

const API_KEY = process.env.IMMO_API_KEY;

async function safeFetch(url: string, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, {
        headers: {
          'Authorization': `Bearer ${API_KEY}`
        }
      });

      if (response.status === 401) {
        throw new Error('Clé API invalide');
      }
      if (response.status === 429) {
        const resetTime = response.headers.get('X-RateLimit-Reset');
        console.warn(`Rate limit atteint. Reset: ${resetTime}`);
      }
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      return await response.json();
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(r =>
        setTimeout(r, Math.pow(2, i) * 1000)
      );
    }
  }
}

Les codes d'erreur principaux sont : 400 (paramètres invalides), 401 (clé API manquante ou invalide), 429 (limite de requêtes atteinte) et 500 (erreur serveur). Consultez la documentation complète pour le détail de chaque code d'erreur.

Cas d'usage avancés

Calcul du prix médian au m2

Plutôt que la moyenne, privilégiez la médiane qui est plus robuste face aux valeurs aberrantes :

async function getPrixMedianM2(codeCommune: string) {
  const mutations = await getAllMutations(codeCommune);

  const appartements = mutations.filter(
    (m: any) => m.type_local === 'Appartement'
      && m.surface_reelle_bati > 0
      && m.valeur_fonciere > 0
  );

  const prixM2 = appartements
    .map((m: any) => m.valeur_fonciere / m.surface_reelle_bati)
    .filter((p: number) => p > 500 && p < 25000)
    .sort((a: number, b: number) => a - b);

  if (prixM2.length === 0) return null;

  const mid = Math.floor(prixM2.length / 2);
  const mediane = prixM2.length % 2 === 0
    ? (prixM2[mid - 1] + prixM2[mid]) / 2
    : prixM2[mid];

  return Math.round(mediane);
}

Notez le filtre p > 500 && p < 25000 qui exclut les valeurs aberrantes (donations déguisées, transactions multi-lots mal renseignées). Pour un calcul encore plus fiable, utilisez directement l'endpoint /v1/stats qui applique ces filtres côté serveur et renvoie le prix médian pré-calculé.

Analyse des tendances de prix

En récupérant les statistiques sur plusieurs années, vous pouvez tracer l'évolution des prix et détecter les tendances :

const API_KEY = process.env.IMMO_API_KEY;

async function getEvolutionPrix(codeDepartement: string) {
  const annees = [2019, 2020, 2021, 2022, 2023, 2024];
  const evolution = [];

  for (const annee of annees) {
    const stats = await safeFetch(
      `https://immoapi.app/v1/stats?code_departement=${codeDepartement}&annee=${annee}&type_local=Appartement`
    );
    evolution.push({
      annee,
      prix_median_m2: stats.prix_median_m2,
      nombre_transactions: stats.nombre_transactions
    });
  }

  return evolution;
}

// Exemple : évolution des prix à Paris
const evolution = await getEvolutionPrix('75');
evolution.forEach(e =>
  console.log(`${e.annee}: ${e.prix_median_m2} euros/m2 (${e.nombre_transactions} ventes)`)
);

Ce type d'analyse permet de constater, par exemple, que le prix médian au m2 parisien a reculé d'environ 5 à 8 % entre 2020 et 2024, alors que certaines métropoles régionales (Lyon, Bordeaux, Nantes) ont connu des hausses significatives sur la même période.

Comparaison entre communes

Pour comparer les prix entre plusieurs communes, utilisez l'endpoint /v1/stats en boucle :

const communes = [
  { code: '75056', nom: 'Paris' },
  { code: '69123', nom: 'Lyon' },
  { code: '13055', nom: 'Marseille' },
  { code: '31555', nom: 'Toulouse' },
  { code: '33063', nom: 'Bordeaux' }
];

for (const commune of communes) {
  const stats = await safeFetch(
    `https://immoapi.app/v1/stats?code_commune=${commune.code}&annee=2024&type_local=Appartement`
  );
  console.log(
    `${commune.nom}: ${stats.prix_median_m2} euros/m2 (${stats.nombre_transactions} transactions)`
  );
}

Erreurs courantes à éviter

Voici les erreurs les plus fréquentes rencontrées par les développeurs qui intègrent Immo API pour la première fois :

  • Oublier le header Authorization : toutes les requêtes nécessitent le header Authorization: Bearer YOUR_API_KEY. Sans ce header, l'API retourne systématiquement une erreur 401
  • Ne pas filtrer géographiquement : une requête sans filtre code_commune ou code_departement retournera une erreur 400. Précisez toujours une zone géographique
  • Confondre code INSEE et code postal : le paramètre code_commune attend un code INSEE (ex : 75056 pour Paris), pas un code postal (75001). Un même code postal peut couvrir plusieurs communes, et une grande ville comme Paris ou Lyon n'a qu'un seul code INSEE mais de nombreux codes postaux
  • Ignorer les mutations multi-lots : lorsqu'une transaction porte sur plusieurs lots (appartement + cave + parking), la valeur foncière couvre l'ensemble. Diviser cette valeur par la seule surface de l'appartement donne un prix au m2 artificiellement élevé
  • Ne pas mettre en cache : les données DVF ne changent que deux fois par an. Interroger l'API pour les mêmes paramètres à chaque requête utilisateur est un gaspillage de quota. Mettez en cache les résultats pendant au moins quelques heures

Accéder aux données depuis un agent IA (MCP)

Au-delà de l'API REST classique, Immo API expose également un serveur MCP (Model Context Protocol), le standard qui permet à un agent IA — Claude, Cursor, ou tout client compatible — d'interroger directement les données DVF sans que vous écriviez la couche réseau. Concrètement, vous connectez le serveur une fois, puis vous formulez vos requêtes en langage naturel : « donne-moi le prix médian au m² des appartements vendus à Bordeaux en 2024 ». L'agent traduit la demande en appel d'outil, récupère les mutations et vous renvoie une synthèse.

Ce mode d'accès ne remplace pas l'API REST pour une application en production, mais il est idéal pour le prototypage, l'exploration de données et la création d'assistants métier. Les deux approches partagent la même source et les mêmes filtres géographiques ; vous pouvez démarrer en langage naturel via MCP, puis industrialiser avec les endpoints REST décrits plus haut une fois votre besoin stabilisé.

FAQ — utiliser l'API DVF

Comment obtenir une clé API pour les données DVF ?

Créez un compte sur immoapi.app : votre clé API est disponible immédiatement dans le tableau de bord, sans validation manuelle. Vous la passez ensuite dans le header Authorization: Bearer VOTRE_CLE de chaque requête. Pensez à la stocker dans une variable d'environnement plutôt que dans votre code source, surtout si votre dépôt Git est public.

L'API DVF est-elle gratuite ?

Les fichiers bruts DVF sont gratuits sur data.gouv.fr, mais leur exploitation impose de télécharger et traiter plusieurs gigaoctets deux fois par an. Immo API propose un accès structuré et filtré à partir de 29 euros/mois (plan Starter, 1 000 requêtes/jour) et 49 euros/mois pour un usage illimité en production. Vous payez la simplicité d'intégration, la géolocalisation et les statistiques pré-calculées, pas la donnée elle-même.

Quel langage utiliser pour interroger l'API DVF ?

N'importe quel langage capable d'effectuer une requête HTTP convient : JavaScript/TypeScript avec fetch, Python avec requests, PHP, Ruby, Go, ou simplement cURL en ligne de commande. L'API renvoyant du JSON standard, le parsing est natif dans la plupart des environnements. Les exemples de ce guide couvrent JavaScript, Python et cURL.

Comment gérer les erreurs 401 et 429 ?

Une erreur 401 signale une clé API absente ou invalide : vérifiez le header Authorization. Une erreur 429 indique que vous avez atteint votre limite de requêtes ; consultez les headers X-RateLimit-Remaining et X-RateLimit-Reset, puis implémentez un retry avec backoff exponentiel. Mettre les résultats en cache réduit fortement le risque de 429, car les données DVF ne changent que deux fois par an.

À quelle fréquence les données de l'API sont-elles mises à jour ?

Les données DVF sont publiées deux fois par an, en avril et en octobre, et intégrées à l'API dans les jours qui suivent. Consultez notre calendrier des mises à jour DVF pour connaître la prochaine publication. Un cache de 24 heures côté client est donc parfaitement raisonnable.

Peut-on récupérer toutes les transactions d'une commune en une seule requête ?

Non, la pagination limite chaque réponse à 100 résultats maximum via le paramètre per_page. Pour récupérer l'intégralité d'une commune, parcourez les pages en boucle jusqu'à atteindre le champ total, comme montré dans l'exemple de pagination ci-dessus. Pour un simple agrégat (prix médian, volume), préférez l'endpoint /v1/stats qui calcule le résultat côté serveur en une seule requête.

Pour aller plus loin