Skip to main content

permisapi-client

Client Python officiel de PermisAPI : 1,3 million de permis de construire en France (base Sitadel, permis autorisés depuis 2013, 101 départements) dans une API REST.

Installation

pip install permisapi-client

Démarrage rapide

from permisapi_client import PermisAPI

client = PermisAPI(api_key="pk_live_...")  # clé obtenue sur https://permisapi.fr/#pricing

# Liste paginée : {"data": [...], "pagination": {page, limit, total, has_next, next_url}}
page = client.permits.list(dep_code="75", limit=10)
for permit in page["data"]:
    print(permit["num_pa"], permit["full_address"])
print(page["pagination"]["total"], "permis au total")

# Recherche géographique (PostGIS) : liste de permis, chacun avec distance_m
nearby = client.permits.near(lat=48.8599, lng=2.3423, radius_m=300)

# Détail d'un permis
permit = client.permits.get("07510125V0025")

# Statistiques d'une commune (Paris entier est rangé sous le code 75056 dans Sitadel)
stats = client.stats.commune("75056")
print(stats["total_permits"], stats["granted"], stats["trend_yoy_pct"])

# Toutes les pages, jusqu'à pagination.has_next == False
for p in client.permits.iter_all(dep_code="75", permit_type="PC_LOGEMENT"):
    print(p["num_pa"])

Coût : une recherche (list, iter_all, near, search) décompte 1 requête par permis renvoyé. iter_all sur un département entier peut donc épuiser le quota mensuel de la formule Gratuit (500 requêtes) ou Explorer (5 000).

Formules : Gratuit (1 département, 6 mois d'historique), Explorer (5 départements, 6 mois), Régional (5 départements, historique complet et données avancées), Pro (les mêmes données avancées sur la France entière), Business et Enterprise. Les exemples de cette page portent sur Paris (75).

Données avancées (formules Régional, Pro, Business et Enterprise)

Les formules Gratuit et Explorer reçoivent une erreur 402 sur ces routes.

num_pa = "07510125V0025"

# Ventes immobilières DVF voisines (ventes de 2021 à 2025)
dvf = client.permits.dvf(num_pa, limit=5)
for m in dvf["matches"]:
    print(m["date_mutation"], m["valeur_fonciere"], "EUR à", m["distance_m"], "m")
print("Prix médian au m² :", dvf["dvf_median_price_per_m2"])

# Score d'opportunité marchand de biens v0.3 (note 0-100 et palier)
score = client.permits.score_mdb(num_pa)
print(f"Score : {score['score']}/100 ({score['tier']})")
# Score déjà pré-calculé : components vaut None ; le détail des 11 signaux
# est donné par la route /v1/permits/{num_pa}/score/explain.

# Zonage PLU (constructible, à urbaniser, agricole, naturel)
plu = client.permits.plu(num_pa)
if plu["has_plu"]:
    z = plu["zonage"]
    print(f"Zone {z['code']}, constructible : {z['constructible']}")

# Risques Géorisques (inondation, séisme, sites Seveso proches...)
risks = client.permits.risks(num_pa)
print(f"Risque : {risks['risk_score']}/100 ({risks['risk_tier']})")
for risk in risks["risks"]:
    print(f"- {risk['label']} (PPR : {risk['has_ppr']})")

# Votre avis sur un score
client.permits.score_feedback(
    num_pa=num_pa,
    score_received=72,
    tier_received="high",
    useful=True,
    accuracy="correct",
    comment="Score cohérent avec notre analyse du quartier.",
)

Export CSV (Business et Enterprise)

# Plafond : 100 000 lignes en Business, 1 000 000 en Enterprise
csv_bytes = client.permits.export(
    dep_code="75",
    permit_type="PC_LOGEMENT",
    date_from="2024-01-01",
    max_rows=5000,
)
with open("paris.csv", "wb") as f:
    f.write(csv_bytes)

Serveur MCP (Claude, ChatGPT, Cursor)

Le serveur MCP officiel (paquet séparé permisapi-mcp) permet à Claude, ChatGPT, Claude Desktop, Cursor et Windsurf d'interroger PermisAPI en langage naturel :

pip install permisapi-mcp

Configurez votre clé dans le client MCP, puis demandez directement :

« Liste les permis de logement autorisés à Paris ce mois-ci »

Mise en place complète : permisapi.fr/mcp.

Async

import asyncio
from permisapi_client import AsyncPermisAPI

async def main():
    async with AsyncPermisAPI(api_key="pk_live_...") as client:
        page = await client.permits.list(dep_code="75")
        print(page["pagination"]["total"])
        async for p in client.permits.iter_all(dep_code="75", permit_type="PC_LOGEMENT"):
            print(p["num_pa"])

asyncio.run(main())

Alertes par webhook

alert = client.alerts.create(
    name="Paris 18e rénovations",
    center_lat=48.88,
    center_lng=2.35,
    radius_km=3,
    permit_types=["PC_LOGEMENT"],
    webhook_url="https://votre-application.fr/permisapi-hook",
)
# Le webhook_secret n'est renvoyé qu'ICI : conservez-le pour vérifier les signatures HMAC.
print(alert["webhook_secret"])

Gestion des erreurs

from permisapi_client import (
    PermisAPI,
    PermisAPIRateLimited,
    PermisAPIQuotaExceeded,
    PermisAPIUnauthorized,
)

try:
    client.permits.list(dep_code="75")
except PermisAPIUnauthorized:
    print("Clé API invalide")
except PermisAPIQuotaExceeded:
    print("Quota mensuel atteint : il se renouvelle le 1er du mois (UTC)")
except PermisAPIRateLimited as e:
    print(f"Trop de requêtes par minute, nouvel essai possible dans {e.retry_after} s")

Licence

MIT. Source des permis : SDES, base Sitadel, data.gouv.fr (Licence Ouverte Etalab).

Liens

Metadata

Release files for permisapi-client 0.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for permisapi-client 0.8.1
File Size Uploaded Provenance
permisapi_client-0.8.1.tar.gz 17.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for permisapi-client 0.8.1
File Interpreter ABI Platform
permisapi_client-0.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 31.6 kB

Release files / permisapi_client-0.8.1.tar.gz

Download URL permisapi_client-0.8.1.tar.gz
Size 17.3 kB
Tags Source
SHA-256 checksum
How to use checksums
8f0ba9287c9807a7e99e77f908bda30c85d3c5d2fb8607167b24f9bfbd0fcf39
BLAKE2b-256 checksum
How to use checksums
45f32a9c6632b10010683ebab430f381c4d8266d76691139ed489d8814ff5f18
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Release files / permisapi_client-0.8.1-py3-none-any.whl

Download URL permisapi_client-0.8.1-py3-none-any.whl
Size 14.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e3f797e485212613eaffc20526cde87e01fde9ec04ff61538baec95a8f622eeb
BLAKE2b-256 checksum
How to use checksums
baec92cc7b68aa8eb1b051f4219f5793864845c17f2b78df6b0ffc2a80bbd183
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Security for permisapi-client 0.8.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page