PermisAPI
marchands de biens, agents immobiliers, investisseurs, banques.
temps 7 min de lecture.budget 199 EUR/mois (plan Pro), endpoint réservé aux comptes Pro et plus.

Score Opportunité MDB v0.1 : noter chaque permis 0-100 pour décider en 5 ms

Persona : marchands de biens, agents immobiliers, investisseurs, banques. Temps : 7 min de lecture. Budget : 199 EUR/mois (plan Pro), endpoint réservé aux comptes Pro et plus.

TL;DR : on vient de shipper un score 0-100 calculé pour chaque permis qui prédit "est-ce une bonne opportunité Marchand de Biens ?". Heuristique pondérée sur 7 signaux observables, pas de ML. Réponse en 5 ms via GET /v1/permits/{num_pa}/score. Voici la formule, pourquoi on a fait V0.1 plutôt que V1.0 ML, et comment l'utiliser pour passer de 4h à 30 min de tri quotidien.

Le problème métier

Un MDB regarde en moyenne 50 nouveaux permis par semaine sur ses zones. Pour chaque permis il se pose la même question : "Est-ce que ça vaut le coup que je creuse ?". Aujourd'hui sa méthode :

  1. Cliquer le permis dans son outil de veille
  2. Ouvrir la fiche SIRENE du demandeur (pour voir si c'est un particulier ou un promoteur connu)
  3. Ouvrir DVF.app pour estimer le marché du quartier
  4. Estimer mentalement la marge potentielle

5 minutes par permis × 50 = 4 heures par semaine juste pour trier. La majorité de ces permis sont éliminés en 30 secondes (mauvais quartier, gros promoteur, surface inadéquate). Mais il faut quand même ouvrir chaque fiche pour le savoir.

Hypothèse : un score automatique 0-100 calculé une fois par permis, queryable en 5 ms, devrait permettre de pré-filtrer 70-80% des permis sans intervention humaine. On vise un signal qui élimine le bruit, pas un classement parfait.

La formule v0.1

Pas de ML, juste 7 composants additionnés avec des poids fixes documentés. Chaque composant retourne un score 0-100 lui-même, le total est borné à 0-100 après pondération.

Component 1 : Type de permis (poids 20%)

PD                = 95   (démolition pure : très souvent MDB)
DP_LOGEMENT       = 90   (extension/division/ravalement = MDB pur)
DP_UNKNOWN        = 75
PC_LOGEMENT       = 70   (mix MDB rénovation + promoteur neuf)
PC_UNKNOWN        = 65
DP_LOCAUX         = 50
PC_LOCAUX         = 40   (locaux commerciaux : moins MDB)
PA                = 30   (lotissement : promoteur foncier, pas MDB)

Logique : un permis de démolir est presque toujours suivi d'une reconstruction par un MDB (raser pour diviser/transformer). Une déclaration préalable logement c'est typiquement "je transforme cette maison en 3 appartements". Un permis aménager c'est un découpage de parcelles, métier promoteur foncier pas MDB.

Component 2 : Surface terrain (poids 15%)

Sweet spot 200-2000 m² → 100. En dehors, dégressif :

0 m²       → 30  (info manquante, pénalité légère)
100 m²     → 50  (trop petit, pas rentable)
200-2000 m² → 100 (sweet spot)
5000 m²    → 70  (trop gros, métier promoteur)
12000 m²+  → 0   (terrain industriel, hors scope MDB)

Logique : un MDB cherche des opérations rentables sans avoir à gérer la complexité d'un grand terrain (qui appelle un promoteur avec équipe). Un terrain de 100 m² ne permet pas de division. Un terrain de 5 000 m² c'est un projet de lotissement, pas du MDB.

Component 3 : DVF voisin €/m² (poids 25% — le plus lourd)

Médiane prix/m² des transactions DVF voisines (top 5 matches déjà précalculés par notre cross-ref DVF) :

1000 €/m²  → 0    (rural ultra-peu cher, marge faible)
4000 €/m²  → 33
7000 €/m²  → 67
10000 €/m²+ → 100  (plafond, marchés ultra-tendus)

C'est le composant le plus déterminant car la marge MDB scale presque linéairement avec le prix au m². Une revente à 10 000 €/m² Paris 16 sur un appartement de 80 m² rénové = 800 k€ × 30% marge = 240 k€ par opération. À 2 000 €/m² rural, c'est 80 k€ × 20% = 16 k€. Pas le même métier.

Component 4 : Activité du département (poids 10%)

Top 13 deps (59, 44, 33, 31, 35, 29, 56, 67, 85, 62, 75, 69, 13)  → 100
Mid 17 deps (06, 34, 38, 76, 57, 63, 77, 78, 92, 93, ...)          → 70
Autres                                                              → 40

Logique : un permis dans un dep avec 9 000 permis/an signifie un marché liquide. Un permis dans la Lozère (200 permis/an) signifie une revente lente, immobilisation longue, donc moins MDB.

Component 5 : Demandeur (poids 15%)

Particulier ou SCI               → 90 ("SCI LES TILLEULS", "DUPONT JEAN")
SARL/SAS standard                → 65 ("SARL MARTIN CONSTRUCTION")
Particulier non-précisé          → 75
Gros promoteur national          → 20 ("VINCI", "BOUYGUES", "NEXITY", "EIFFAGE", ...)
Inconnu                          → 50

Logique : un gros promoteur (Vinci, Nexity, Bouygues) a déjà sécurisé l'opération. Un MDB qui débarque trop tard ne peut rien faire. Les SCI sont quasi-systématiquement le véhicule juridique des MDB, donc une SCI déposante = signal très fort que c'est une opportunité de co-deal ou de revente à un MDB plus capé.

Component 6 : Cohérence DVF/permis (poids 10%)

Si un permis logement est entouré de DVF résidentiels = OK. Si entouré de DVF locaux commerciaux = bizarre, drop le score.

PC_LOGEMENT entouré de 100% résidentiel  → 100
PC_LOGEMENT entouré de 50/50              → 50
PC_LOGEMENT entouré de 100% locaux        → 0

Logique : un permis logement déposé dans une zone d'activité industrielle = projet atypique, probablement reconversion d'un local en logement. Possible mais rare et risqué pour un MDB qui veut du standard.

Component 7 : Densité INSEE (poids 5% — le moins lourd)

Classe 1 (Dense)            → 80
Classe 2 (Intermédiaire)    → 70
Classe 3 (Rural)            → 50

Le sweet spot MDB est plutôt urbain/périurbain (classes 1-2) : marges hautes mais opérations complexes en classe 1, plus simples en classe 2. Le rural (classe 3) reste viable mais avec liquidité réduite.

Le score combiné

score = (
    0.20 * type_score +
    0.15 * surface_score +
    0.25 * dvf_value_score +
    0.10 * dep_activity_score +
    0.15 * demandeur_score +
    0.10 * dvf_coherence_score +
    0.05 * density_score
)

Tier dérivé du score :

ScoreTierRecommandation
0-30lowÀ skip (gros promoteur, mauvais quartier, ou surface aberrante)
30-60mediumMérite un coup d'œil rapide
60-80highOpportunité réelle, à investiguer
80-100premiumÀ investiguer en priorité

Une réponse concrète

Permit 0330632500527 à Bordeaux, 13 rue de Vaucouleurs (PC_LOGEMENT, surface 169 m², demandeur particulier non-mentionné) :

curl -H "X-API-Key: pk_live_..." \
  https://api.permisapi.fr/v1/permits/0330632500527/score
{
  "num_pa": "0330632500527",
  "score": 78,
  "tier": "high",
  "components": {
    "type": 70,
    "surface": 100,
    "dvf_value": 43,
    "dep_activity": 100,
    "demandeur": 75,
    "dvf_coherence": 100,
    "density": 70
  },
  "weights": {
    "type": 0.20, "surface": 0.15, "dvf_value": 0.25,
    "dep_activity": 0.10, "demandeur": 0.15,
    "dvf_coherence": 0.10, "density": 0.05
  },
  "version": "v0.1",
  "method": "heuristique pondérée (7 signaux)",
  "dvf_matches_used": 5,
  "density_class": 2
}

Le tier "high" (78) dit immédiatement au MDB : "prend 5 minutes pour creuser ce permis". La répartition des composants montre pourquoi :

  • Surface 100% (169 m² dans le sweet spot)
  • Cohérence DVF 100% (entouré de maisons, cohérent avec le permis logement)
  • Activité dep 100% (Bordeaux Gironde top 3)
  • Mais DVF value modéré (43) car prix/m² Bordeaux périphérique pas exceptionnel

Si le même permis avait été déposé par "VINCI CONSTRUCTION FRANCE", le composant demandeur serait passé de 75 à 20, le score total chuterait de 78 à ~70 (toujours high mais moins prioritaire car déjà dans le pipeline d'un gros).

Pourquoi V0.1 et pas V1.0 ML

V0.1 (maintenant)V1.0 (plus tard)
MéthodeHeuristique pondérée fixeModèle ML (random forest ou XGBoost)
Effort1 journée1-2 semaines + data labeled
Data nécessaire0 client (signals existants)Feedback users : "ce score était juste/faux" sur 500-1000 permits
Précision attendue~70% bonne corrélation MDB~85-90% si bien entraîné
ExplicabilitéTransparente (les 7 components retournés)Black box (SHAP values pour expliquer)
MaintenanceTweak les poids dans le codeRe-training pipeline, drift monitoring, versions

Stratégie ship V0.1 maintenant : on collecte les feedbacks dans la prod ("ce score était utile / faux pour mon cas") via un endpoint /v1/score/feedback (V0.2) puis on entraîne un V1.0 ML quand on a 500-1000 labels.

C'est le pattern "ML-ready, but rule-based first" qu'utilisent les boîtes mature : Stripe Radar a démarré en règles avant d'être ML, Slack Highlights aussi. Le client ne saura jamais le switchover.

Limites connues V0.1

  1. Pas de feedback loop encore. Le score est calculé à la volée à chaque appel, on ne stocke pas les feedbacks users. V0.2 ajoutera un endpoint /v1/score/feedback qui collectera "ce score était utile" / "ce score était faux pour mon cas".
  2. Poids hardcodés. Pas d'A/B test des pondérations. Si on découvre que "surface" doit peser 25% plutôt que 15%, on doit pousser une nouvelle version. Acceptable pour V0.1.
  3. Pas de filtrage SQL ?min_score=N sur /v1/permits. Calculer le score à la volée pour 100 permis dans une page ferait 100 sub-queries DVF. V0.2 matérialisera le score dans permits.score_mdb avec un cron mensuel. Pour l'instant, on ne supporte que le calcul individuel.
  4. Particulier vs SCI. Notre détection demandeur est basée sur des keywords ("SCI", "VINCI", ...). Si une SCI s'appelle "Société Foncière du Petit Pont" sans le préfixe SCI, on lui donne un score particulier. Cas marginal mais existant.
  5. Pas de signal "BODACC SCI nouvellement créée". Une SCI créée la semaine dernière qui dépose un permis = signal MDB ultra-fort. V0.2 cross-référencera avec BODACC.

L'utiliser dans votre stack

L'endpoint est documenté sur https://api.permisapi.fr/docs#/permits/get_permit_score_mdb. Plan Pro à 199 EUR/mois inclut Score MDB v0.1 + DVF cross-ref + Cadastre + SIRENE + France entière + historique complet.

from permisapi_client import PermisAPI

client = PermisAPI(api_key="pk_live_...")

# Score 1 permit
result = client.permits.score_mdb("PC07404021K1")
print(result["score"], result["tier"])

# Iterate sur ses permis récents et garder les "high" ou "premium"
for permit in client.permits.iter_all(dep_code="33", limit=100):
    score = client.permits.score_mdb(permit["num_pa"])
    if score["score"] >= 60:
        print(f"{permit['num_pa']}: {score['score']} ({score['tier']}) - {permit['adr_localite_ter']}")

Vue 360° dans le dashboard /dashboard/explore qui combine permit + SIRENE + DVF + Score en 1 clic : tape un num_pa, presse "Tout récupérer", vois le score gros affiché en couleur du tier + les 4 sections détaillées.

Le ROI pour un MDB

Avant Score MDB : 50 permis × 5 min de tri = 4h/semaine rien que pour décider quoi creuser.

Avec Score MDB v0.1 : ?score >= 60 filtre = 5-10 permis restants à investiguer × 5 min = 30-50 min/semaine.

Soit ~3h30 économisées par semaine = ~14h par mois. À 100 €/h consultant équivalent = 1 400 € par mois économisés. Pour 199 € de plan Pro qui inclut aussi DVF + SIRENE + Cadastre. Le ROI est 7x sur ce seul use case.

Et si tu rates UN deal grâce au filtre (ce qui peut arriver, V0.1 n'est pas parfait), c'est dans le bruit statistique : tu en gagnes 5 autres en cherchant moins. La précision V0.1 ~70% est largement suffisante pour le top-of-funnel triage. Pour la décision d'achat finale, tu re-investigues à la main les 5-10 permis "high"/"premium" comme avant.

Pourquoi on l'a construit

J'ai eu un retour précis d'un MDB Bordeaux : "Ton API DVF cross-ref c'est cool mais le tri reste manuel. Si tu pouvais juste me dire combien chaque permis vaut le coup, là je signe Pro tout de suite." Une semaine plus tard, ce score est shipped.

Cette feature est aussi une bonne illustration du pattern "intelligence layer" vs "data wrapper". PermisAPI ne se contente plus de retourner les data Sitadel : on les enrichit (BAN), on les croise (SIRENE, DVF, Cadastre), et maintenant on les interprète (Score MDB). Chaque couche augmente la valeur ajoutée vs le coût marginal de produire (la data brute reste publique gratuite, l'interprétation devient un produit).

V1.0 ML viendra quand on aura 500-1000 feedbacks users. En attendant, V0.1 est testable maintenant, retourne un signal utile en 5 ms, et économise ~14h/mois à un MDB qui investigue 50 permis/semaine.

Suite

Si vous testez le Score MDB et trouvez des cas où il se trompe (faux positifs ou faux négatifs), écrivez-moi à evan@permisapi.fr avec le num_pa et votre verdict. Ces feedbacks alimenteront directement le V0.2 (poids ajustés) puis V1.0 (modèle ML).

Et si vous avez des suggestions d'autres signaux à inclure (BODACC, IRIS INSEE socio-démo, distance école, ...) la liste est ouverte. La formule v0.1 a été conçue pour rester transparente et tweakable rapidement.

Essaie l'API en 30 secondes

Pas de signup, pas de carte bleue. Entre un code postal sur la home et regarde 5 permis en temps reel.

Autres tutoriels