Documentation API v1
Base URL : https://cherchertrouver.immo/api/v1
Des chapitres réservés s’affichent ici une fois connecté au compte auquel nous les avons ouverts.
Ces exports contiennent toute la référence en un seul fichier : points d’accès, paramètres, bornes et codes de réponse. Un assistant les ingère d’un bloc et sait ensuite appeler l’API sans inventer de paramètre.
https://cherchertrouver.immo/llms.txt
Authentification
Toutes les requêtes doivent inclure votre clé API. Deux méthodes acceptées :
X-Api-Key: imk_votre_cle
Authorization: Bearer imk_votre_cle
Limites & quotas
Chaque réponse acceptée inclut ces en-têtes pour surveiller votre consommation. Une réponse 429 porte Retry-After et X-Annonces-From, mais pas les compteurs de quota :
| En-tête | Description |
|---|---|
X-RateLimit-Limit | Nombre max de requêtes par minute |
X-RateLimit-Remaining | Requêtes restantes dans la fenêtre courante |
X-RateLimit-Reset | Horodatage UNIX de réinitialisation de la fenêtre |
X-Quota-Items-Limit | Quota journalier d’annonces retournées |
X-Quota-Items-Used | Annonces déjà consommées sur les dernières 24h |
X-Quota-Mois-Limit | Quota d’annonces de la période (offre souscrite) |
X-Quota-Mois-Used | Annonces déjà découvertes sur la période |
X-Quota-Mois-Remaining | Ce qu’il vous reste sur la période |
X-Quota-Mois-Reset | Date de remise à zéro, sur un abonnement (absent sur la fenêtre glissante de l’offre gratuite) |
X-Annonces-From | Date à partir de laquelle votre clé reçoit les annonces (cf. Périmètre du catalogue) |
/ping ne consomme pas de quota.
Les quatre en-têtes X-Quota-Mois-* sont absents
si votre compte n’a pas de quota mensuel : c’est le cas des comptes
ouverts avant la mise en place des paliers, qui conservent leur régime
d’origine et son seul plafond journalier.
Un plafond distinct limite le nombre total de requêtes/jour (anti-interrogation abusive).
402 de code ITEMS_QUOTA : le corps porte
quota, consomme, la date de reprise
(repart_le sur un abonnement, se_libere_le sur
la fenêtre glissante) et le palier_suivant.
Pour distinguer un quota atteint d'une panne :
/ping continue de répondre. Les autres points d'accès
d'annonces, eux, renvoient tous 402, y compris pour une annonce que vous
connaissez déjà : le refus est posé avant la recherche.
| Offre | Annonces / mois | Annonces uniques / jour | Requêtes / jour | Req / min | Req / s |
|---|---|---|---|---|---|
| Découverte | 50 | 200 | 300 | 60 | 1 |
| Secteur | 1 000 | 200 | 600 | 60 | 1 |
| Ville | 5 000 | 500 | 1 500 | 60 | 1 |
| Département | 20 000 | 2 000 | 6 000 | 60 | 1 |
| Région | 60 000 | 6 000 | 18 000 | 120 | 2 |
| National | 150 000 | 15 000 | 45 000 | 300 | 5 |
| Plateforme | 400 000 | 40 000 | 120 000 | 600 | 10 |
| Sur mesure | Nous consulter | Nous consulter | Sur mesure | Sur mesure | Sur mesure |
Périmètre du catalogue
Deux règles distinguent ce que renvoie l’API de ce qu’affiche la page publique. Elles jouent en sens inverse : la première réduit le périmètre, la seconde l’élargit.
1. Date de début d’accès
Une clé ne restitue que les annonces entrées dans notre
catalogue à partir d’une date donnée, renvoyée dans l’en-tête
X-Annonces-From de chaque réponse. Par défaut, cette date
est celle de la création de votre compte : l’abonnement
porte sur le flux courant, l’historique constitué avant votre arrivée
étant proposé en option.
- Elle dépend du compte, pas de la clé : en révoquer une et en créer une autre ne déplace pas cette date.
-
Elle porte sur la date d’entrée dans notre base, et non
sur la date de publication sur le site d’origine ni sur
updated_at. Le paramètreupdated_sincene permet donc pas de remonter au-delà. - Elle s’applique à toutes les offres, gratuite comme payantes.
2. Aucun filtre de fraîcheur
La page publique n’affiche que les annonces revues dans les deux dernières semaines. L’API lève cette contrainte : elle vous sert aussi les annonces que nous n’avons pas revues depuis, sur la période à laquelle vous avez accès. C’est délibéré : une veille incrémentale a besoin de revoir une annonce même quand elle cesse d’être rafraîchie.
En revanche, une annonce explicitement passée à vendue, sous compromis ou archivée sort du flux, sur l’API comme sur le site. Une annonce qui disparaît de vos résultats est donc soit vendue, soit hors de votre période d’accès : ne déduisez pas de sa présence qu’un bien est toujours disponible, ni de son absence qu’il a été vendu.
Pour vous rapprocher de ce qu’affiche le site, filtrez avec
updated_since : il porte sur la date de notre dernier
passage de collecte, exposée dans le champ updated_at. Une
annonce que nous n’avons pas revue depuis deux semaines a de fortes
chances de ne plus être en ligne.
Format des erreurs
Toutes les erreurs retournent un JSON avec error (message lisible) et code (identifiant machine) :
{
"error": "Limite de requêtes dépassée (60 req/min max)",
"code": "RATE_LIMIT_PER_MIN",
"retry_after_seconds": 42
}
| HTTP | Code | Cause |
|---|---|---|
| 401 | API_KEY_MISSING | Aucune clé fournie |
| 401 | API_KEY_INVALID | Clé invalide, révoquée ou bloquée |
| 400 | BAD_REQUEST | Paramètres invalides (détails dans details[]) |
| 404 | NOT_FOUND | Ressource introuvable |
| 429 | RATE_LIMIT_PER_SEC | Limite par seconde dépassée |
| 429 | RATE_LIMIT_PER_MIN | Limite par minute dépassée |
| 402 | QUOTA_EXCEEDED | Quota journalier d’annonces atteint |
| 402 | ITEMS_QUOTA | Quota d’annonces de la période atteint : le corps porte la date de reprise et le palier suivant |
| 402 | PAID_PLAN_REQUIRED | Filtre par site (sources, exclude_sources, /sources), réservé aux offres à partir de 118,80 € TTC par mois |
/api/v1/ping
Health check, vérifie que votre clé est valide et retourne les limites configurées pour votre offre. Utile pour tester l’authentification sans consommer de quota.
items_per_day est le plafond d’annonces
distinctes par jour, distinct du volume mensuel de votre offre.
Il vaut le dixième du volume mensuel, avec un minimum de
200. L’offre
Secteur
(1 000 annonces par mois
pour 12 € TTC)
est ainsi bornée à
200 annonces par
jour. Le plafond de chaque offre figure aussi sur la
page des tarifs.
{
"ok": true,
"api_key_name": "Clé personnelle",
"tier": "free",
"rate_limit_per_sec": 1,
"rate_limit_per_min": 60,
"items_per_day": 200,
"server_time": "2026-04-18T10:00:00.000Z"
}
/api/v1/annonces
Recherche d’annonces, rendue par pages. Tous les filtres sont optionnels. Les partenaires API accèdent au catalogue complet, sans filtre de récence.
| Paramètre | Type | Description |
|---|---|---|
q | string | Recherche plein texte (titre, description) |
type | string | Type de bien : Appartement, Maison, Terrain… |
transaction | enum | vente ou location |
ville | string | Nom de ville (ex : Paris, Lyon) |
cp | string | Code postal (ex : 75015) |
dept | string | Numéro de département (ex : 75, 2A) |
region | string | Nom de région (ex : Bretagne) |
| Prix | ||
prix_min | integer | Prix minimum (€) |
prix_max | integer | Prix maximum (€) |
prix_m2_min | integer | Prix au m² minimum |
prix_m2_max | integer | Prix au m² maximum |
| Surface & caractéristiques | ||
surface_min | number | Surface minimale (m²) |
surface_max | number | Surface maximale (m²) |
pieces_min | integer | Nombre de pièces minimum |
chambres_min | integer | Nombre de chambres minimum |
annee_min | integer | Année de construction minimale. Renseignée sur environ 35 % des annonces : ce filtre écarte donc aussi les biens dont nous ne connaissons pas l’année. À utiliser pour trouver du récent à coup sûr, pas pour affirmer qu’un secteur n’en a pas. |
annee_max | integer | Année de construction maximale. Même réserve de couverture. |
| DPE / GES | ||
dpe | string ou array | Classes DPE : A,B,C ou dpe=A&dpe=B |
ges | string ou array | Classes GES (même format) |
| Veille incrémentale (date) | ||
updated_since |
ISO 8601 |
Annonces (re-)collectées depuis cette date (= colonne
updated_at de la réponse). À combiner avec
sort=recent pour faire de la veille incrémentale
fiable (« donne-moi ce qui a bougé depuis ma dernière poll »).
Ex : updated_since=2026-06-09T00:00:00Z.
|
created_since |
ISO 8601 |
Annonces dont la mise en ligne sur le site source
est postérieure à cette date (= colonne published_at).
Moins fiable que updated_since pour la veille
(certaines annonces sont ré-éditées sans changer leur date pub).
|
| Pages & tri | ||
page | integer | Page demandée (défaut : 1, max : 1000) |
page_size | integer | Résultats par page (défaut : 25, max : 100) |
cursor |
string opaque |
Parcours par repère : chaque réponse porte le point
de reprise de la suivante. À préférer dès qu’on descend loin
dans les résultats.
Au lieu d'incrémenter page, passer la valeur de
next_cursor reçue dans la réponse précédente. O(1)
par page quelle que soit la profondeur (vs page=N
qui devient lent au-delà de 50 pages). Compatible avec tous les
autres filtres ; ne pas envoyer page en même temps
(cursor prend le pas).
|
sort |
enum |
recent (tri par updated_at DESC : date de
collecte, idéal veille incrémentale) ·
price_asc · price_desc ·
surface_desc · pricem2_asc
|
source | enum | all (défaut) · interne · scraped |
sources | liste |
Ne garder que ces sites : site_a,site_b.
Identifiants exacts servis par GET /sources.
offre payante
|
exclude_sources | liste |
Tout garder sauf ces sites :
site_a. Plus pratique que sources
quand on veut presque tout, et plus robuste : une liste
blanche se périme dès qu’un site est ajouté, une liste
noire non. Combinable avec sources : la
différence est appliquée.
offre payante
|
updated_at de la
plus récente annonce reçue. Au poll suivant, requêter avec
updated_since=<cette_date>&sort=recent et
itérer via next_cursor jusqu'à has_more=false.
Pour une fenêtre de 20 000 annonces, page_size=50 donne 400 pages,
toutes accessibles en O(1) par page via le cursor. Aucun re-scan
complet du catalogue n'est nécessaire.
/annonces/feed : une seule boucle, un curseur, zéro trou.
$ # Première page $ curl -H "X-Api-Key: imk_xxx" \ "https://cherchertrouver.immo/api/v1/annonces?updated_since=2026-06-09&sort=recent&page_size=50" # → réponse contient "next_cursor": "eyJ1IjoiMjAyNi0wNi0...=" $ # Page suivante : passer next_cursor reçu $ curl -H "X-Api-Key: imk_xxx" \ "https://cherchertrouver.immo/api/v1/annonces?cursor=eyJ1IjoiMjAyNi0wNi0...="
$ curl -H "X-Api-Key: imk_xxx" \ "https://cherchertrouver.immo/api/v1/annonces?ville=Nantes&type=Appartement&prix_max=350000&page_size=5"
{
"page": 1,
"page_size": 5,
"has_more": true,
"next_cursor": "eyJ1IjoiMjAyNi0wNi0wOVQwMjozMjowMC4wMDBaIiwiciI6ImFiYzEyMyIsInMiOiJzZWxvZ2VyIn0",
"items": [
{
"source": "site_a",
"reference": "abc123",
"title": "Appartement 3 pièces 68m² Nantes Centre",
"type": "Appartement",
"transaction_type": "vente",
"price": 312000,
"price_per_m2": 4588,
"price_per_m2_color": "#f59e0b",
"price_label": null,
"surface": 68,
"land_surface": null,
"living_room_surface": 28,
"rooms": 3,
"bedrooms": 2,
"bathrooms": 1,
"shower_rooms": 1,
"toilets": 1,
"kitchen": "équipée",
"year_built": 1975,
"elevator": true,
"parking": false,
"parking_interior": null,
"parking_exterior": null,
"cellar": true,
"garden": false,
"seller_type": "Pro",
"seller_name": "Agence Centre Immo",
"real_estate_network": "Réseau Exemple",
"exclusive": true,
"city": "Nantes",
"postal_code": "44000",
"department": "44",
"region": "Pays de la Loire",
"latitude": 47.2184,
"longitude": -1.5536,
"dpe": "D",
"ges": "D",
"dpe_value": 210,
"ges_value": 42,
"dpe_chart_url": "https://...",
"ges_chart_url": null,
"legal_info": "Copropriété de 24 lots...",
"images": ["https://..."],
"images_count": 8,
"description": "Bel appartement lumineux...",
"external_url": "https://site-a.example/...",
"video_url": null,
"virtual_tour_url": "https://...",
"published_at": "2026-04-15T08:23:00.000Z",
"updated_at": "2026-09-05T04:12:00.000Z",
"seller_contact": null,
"price_history": {
"current": 312000,
"previous": 325000,
"changed_at": "2026-08-14T03:12:00.000Z",
"changes": 2,
"tracked_since": "2026-06-23T02:10:00.000Z",
"depth": 2
},
"is_internal": false,
"dedup_key": "a1b2c3d4e5f60718",
"sources": [
{ "source": "site_a", "reference": "123456", "url": "https://site-a.example/...", "price": 415000, "is_main": true },
{ "source": "site_b", "reference": "789012", "url": "https://site-b.example/...", "price": 418000, "is_main": false }
]
}
]
}
price_history) : les deux derniers
prix relevés sur l’annonce, dans toutes les offres. null tant que
nous n’avons aucun relevé.
currentetprevious: le dernier prix et celui d’avant.previousvautnullquand le prix n’a pas bougé depuis que nous suivons l’annonce : ce n’est pas une donnée manquante, c’est un prix stable.tracked_since: la date de notre PREMIER relevé. Toute variation se compte à partir de là, jamais depuis la mise en vente : nous ne connaissons pas le prix d’une annonce avant de l’avoir vue. Un relevé par heure, sur les annonces actives, au seuil de 1 %.depth: le nombre de prix réellement renvoyés. Il vaut 2 sans la série, sinon la longueur depoints. Lisez-le plutôt que de déduire votre offre de l’absence d’un champ.- Profondeur attendue : le suivi a commencé le 23 juin 2026, et aucune annonce n’a donc davantage d’antériorité. Un bien mis en vente avant cette date arrive chez nous avec le prix qu’il avait ce jour-là, pas avec son historique complet.
points: la série complète des relevés, réservée aux offres à partir de 118,80 € TTC par mois et servie uniquement sur la fiche d’une annonce (/annonces/{source}/{reference}). Sur/annonceset le flux, aucune offre ne la reçoit.
source = le site principal).
dedup_key: identifiant stable du groupe de doublons (même bien = même clé sur tous les sites).nullsi l'annonce n'a pas de doublon connu.sources: la liste de TOUS les sites du groupe (le principal + les doublons), chacun avecsource,reference,url,priceetis_main.nulls'il n'y a pas de doublon.<champ>_source: quand une info manquante a été complétée depuis un doublon d'un autre site, ce champ en indique la provenance. Exemple : une annonce sans description qui récupère celle d'un doublon publié sur un autre site renvoie"description_source": "site_b". S'applique à la description, au titre, aux photos et aux caractéristiques (ex :bedrooms_source,dpe_source). Absent si le champ provient de l'annonce elle-même.- Pour recevoir tous les doublons non regroupés (comportement
historique), ajouter
?dedup=0.
null = information non disponible pour cette annonce.
seller_type vaut "Pro", "Particulier" ou null.
Les booléens d'équipement (elevator, parking,
parking_interior, parking_exterior,
cellar, garden, exclusive) valent
true, false ou null (inconnu).
dpe_value / ges_value sont les valeurs numériques
exactes (kWh/m²/an et kg CO₂/m²/an) quand l'annonce les fournit, en
complément des lettres dpe / ges.
/api/v1/annonces/feed
Flux complet du catalogue. Conçu pour un seul besoin :
récupérer toutes les annonces qui entrent en base, puis rester
à jour en continu, sans jamais en manquer ni gérer de pages. Une seule
boucle : on rappelle avec le next_cursor reçu, indéfiniment.
page (limitée à 1000 pages, soit ~100 000 annonces), le flux
parcourt l’intégralité du catalogue puis suit les nouveautés sans limite.
| Paramètre | Type | Description |
|---|---|---|
cursor |
string opaque |
Position de reprise. Absent au 1er appel (démarre au plus
ancien). Ensuite, réinjecter la valeur next_cursor de la réponse
précédente. À conserver côté client pour reprendre après un redémarrage.
|
page_size | integer | Annonces par page (défaut : 100, max : 100) |
| Filtres | divers |
Tous les filtres de /annonces
(type, ville, dept,
prix_max…) sont acceptés pour ne suivre qu’un
sous-flux. Sans filtre : tout le catalogue.
|
- Appeler sans
cursorau démarrage. - Traiter
items, enregistrernext_cursor, rappeler avec?cursor=<next_cursor>. - Répéter tant que
itemsn’est pas vide : vous parcourez tout le catalogue (rattrapage initial). itemsvide (has_more=false) : vous êtes à jour. Attendre (1 à 5 min) puis rappeler avec le mêmecursor: les nouvelles annonces arrivent au fil de l’eau.
(source, reference). Le flux est un
change-feed : une annonce ré-analysée réapparaît (données à jour).
Les sites d’un même bien sont livrés séparément (pas de regroupement).
$ # Premier appel (sans cursor) $ curl -H "X-Api-Key: imk_xxx" \ "https://cherchertrouver.immo/api/v1/annonces/feed?page_size=100" # → réponse : "next_cursor": "eyJ1IjoiMjAyNi0wNy0wMS...=" $ # Appels suivants : réinjecter next_cursor. Page vide = à jour → re-poller plus tard. $ curl -H "X-Api-Key: imk_xxx" \ "https://cherchertrouver.immo/api/v1/annonces/feed?cursor=eyJ1IjoiMjAyNi0wNy0wMS...="
{
"count": 100,
"has_more": true,
"next_cursor": "eyJ1IjoiMjAyNi0wNy0wMVQxMDowMDowMFoiLCJyIjoiYWJjMTIzIiwicyI6ImxlYm9uY29pbiJ9",
"items": [
{
"source": "site_b",
"reference": "abc123",
"title": "Studio 30m² Paris 15e",
"price": 385000,
"surface": 30,
"city": "Paris",
"postal_code": "75015",
// ... mêmes champs que /annonces
}
]
}
next_cursor est toujours présent (même quand items est
vide) pour permettre la reprise. Il vaut null uniquement si la
base est momentanément indisponible. Le quota ne compte que les annonces
nouvelles : un renvoi ne consomme rien.
/api/v1/annonces/map
Retourne les points géographiques d’une zone définie par son rectangle
englobant. Format léger, taillé pour alimenter une carte Leaflet ou Mapbox.
Accepte les mêmes filtres que /annonces.
| Paramètre | Requis | Description |
|---|---|---|
bbox |
Oui | Rectangle englobant, au format sud,ouest,nord,est (degrés décimaux) |
$ curl -H "X-Api-Key: imk_xxx" \ "https://cherchertrouver.immo/api/v1/annonces/map?bbox=47.15,-1.65,47.30,-1.45&type=Maison"
{
"bbox": { "south": 47.15, "west": -1.65, "north": 47.30, "east": -1.45 },
"total": 142,
"capped": false,
"items": [
{
"source": "site_b",
"reference": "xyz789",
"latitude": 47.2184,
"longitude": -1.5536,
"price": 285000,
"price_per_m2": 2375,
"price_per_m2_color": "#16a34a",
"surface": 120,
"type": "Maison",
"title": "Maison 5 pièces 120m²",
"city": "Nantes",
"postal_code": "44000",
"rooms": 5,
"image": "https://...",
"is_internal": false
}
]
}
capped: true indique que la bbox contient plus d’annonces que la limite retournée (≤ 2 000 points par requête). Zoomez ou affinez les filtres.
/api/v1/annonces/:source/:reference
Retourne le détail complet d’une annonce identifiée par sa source et sa référence. Consomme 1 annonce sur le quota journalier.
| Paramètre | Description |
|---|---|
:source | Identifiant de la source, tel que servi par /annonces/sources |
:reference | Référence unique de l’annonce sur la source (max 128 chars) |
$ curl -H "X-Api-Key: imk_xxx" \ "https://cherchertrouver.immo/api/v1/annonces/site_a/abc123"
{
"annonce": {
"source": "site_a",
"reference": "abc123",
// ... tous les champs (même structure que /annonces)
}
}
/api/v1/ptz/zone
Lookup officiel d’une commune française vers sa zone du prêt à taux zéro (PTZ) (A bis / A / B1 / B2 / C) selon l’arrêté du 5 septembre 2025 du Ministère du Logement. Zonage utilisé par tous les dispositifs aidés : Prêt à Taux Zéro, Pinel, Logement Locatif Intermédiaire, Bail Réel Solidaire, PSLA. Coût : 1 token par lookup réussi (200). Les erreurs (400/404) ne consomment pas.
| Paramètre | Description |
|---|---|
cp requis | Code postal français à 5 chiffres (ex : 75011) |
$ curl -H "X-Api-Key: imk_xxx" \ "https://cherchertrouver.immo/api/v1/ptz/zone?cp=75011"
{
"zone": "Abis",
"codePostal": "75011",
"source": "Arrêté du 5 septembre 2025, Ministère du Logement"
}
{
"error": "Code postal inconnu"
}
zone possibles sont : "Abis" (Paris, ultra-tendu),
"A" (grandes métropoles), "B1" (agglos tendues),
"B2" (villes moyennes), "C" (rural & petites villes, ~81 % du territoire).
Couvre 34 875 communes françaises. Cache HTTP : 24h (la zone d’une commune
ne change que par arrêté ministériel, ~1× par an).