Skip to main content

Documentation Index

Fetch the complete documentation index at: https://doc.fluximmo.io/llms.txt

Use this file to discover all available pages before exploring further.

Copiez intégralement le bloc ci-dessous dans votre prompt LLM (ChatGPT, Claude, Cursor) pour qu’il génère des payloads Fluximmo corrects sans hallucination. Cible: 2-4K tokens.
# Fluximmo API v2 — Context (FR real-estate intelligence)

## 1. Identity
Fluximmo is a French real-estate intelligence API (since 2017). Two core entities:
- Property = unique deduplicated physical asset (1 bien = N adverts merged).
- Advert = one listing on one portal (raw, with events).
Full docs: https://doc.fluximmo.io . Sample no-auth: https://api.fluximmo.io/v2/sample/properties

## 2. Property vs Advert (decision matrix)
| Need                                       | Use         |
|--------------------------------------------|-------------|
| Dedup market view, AVM, marketplace        | Property    |
| Per-listing price drops, republish, offline| Advert      |
| Webhook with full payload + events         | Advert      |
| Webhook IDs only (refetch via GET)         | Property    |
| Lightweight autocomplete / mobile          | Lite search |

## 3. Core types (TS-like)
```ts
type SearchPropertiesPayload = {
  size: number,                                  // 1-100 (full) or 1-25 (lite)
  sortBy: EnumSearchRequestSortBy,
  orderBy: "ASC" | "DESC",
  search: { filterProperty: FilterProperty }
}
type SearchAdvertsPayload = {
  size: number,
  sortBy: EnumSearchRequestSortBy,
  orderBy: "ASC" | "DESC",
  search: { filterAd: FilterAdvert }
}
type SaveSearchPropertiesPayload = {
  search_query: { filterProperty: FilterProperty },
  webhook_url: string,                           // HTTPS public URL
  match: EnumPropertyAlertMatch[],               // ["ALERT_MATCH_CREATED"] is the safe default
  search_name: string,
  context?: { metadata?: Record<string, unknown> } // QueryContextDto — optional
}
type SaveSearchAdvertsPayload = {
  search_query: { filterAd: FilterAdvert },
  webhook_url: string,
  match: EnumAdvertAlertMatch[],
  search_name: string,
  context?: { metadata?: Record<string, unknown> }
}

type FilterProperty = {
  location?: FilterLocation[],                   // OR across array entries
  type?: EnumPropertyClass[],
  offer?: { type: EnumPropertyOfferType }[],
  price?: FilterPropertyPrice,                   // {initial|latest}.value.{min,max}
  habitation?: FilterTypeHabitation,
  meta?: FilterMeta
}
type FilterAdvert = {
  location?: FilterLocation,                     // single object (NOT array — unlike FilterProperty)
  type?: EnumPropertyClass[],
  offer?: { type: EnumPropertyOfferType }[],
  currentPrice?: FilterAdvertPrice,              // field name is `currentPrice` (NOT `price`)
  habitation?: FilterTypeHabitation,
  meta?: FilterMeta,
  isOnline?: boolean                             // production: set to true on alerts
}

type FilterLocation = {
  postalCode?: string,                           // "75011"
  inseeCode?: string,                            // "75056"
  department?: string,                           // "75" (2 chars FR)
  irisCode?: string,
  // city is silently IGNORED by the engine — DO NOT USE
  locationCoordinate?: {
    location: {
      geoBoundingBox?: {                         // topLeft.lat > bottomRight.lat AND topLeft.lon < bottomRight.lon
        topLeft: { lat: number, lon: number },
        bottomRight: { lat: number, lon: number }
      },
      geoDistance?: {                            // Plane distance, not Haversine
        pin: { lat: number, lon: number },
        distanceKm: number                       // > 0 required
      }
    }
  }
}
// NOTE: geoShape / POLYGON not exposed. Use geoBoundingBox or multi-zone OR.

type FilterPropertyPrice = {
  initial?: { value: { min?: number, max?: number } },
  latest?:  { value: { min?: number, max?: number } }
}
type FilterAdvertPrice = {
  value?: { min?: number, max?: number },        // EUR
  valuePerArea?: { min?: number, max?: number }  // EUR per m2
}

type FilterTypeHabitation = {
  surface?: { total?: { min?: number, max?: number } },   // m2
  bedroomCount?: { min?: number, max?: number },
  roomCount?:    { min?: number, max?: number },
  floor?:        { min?: number, max?: number }
}

type FilterMeta = {
  isTotallyOffline?: boolean,                       // PROPERTIES production: set to false
  firstSeenAt?:   { min?: string, max?: string },   // ISO 8601 — production typically min: "2025-01-01T00:00:00.000Z"
  lastSeenAt?:    { min?: string, max?: string },
  lastUpdatedAt?: { min?: string, max?: string }
}
```

## 4. Enums (literal values, exact)
```ts
type EnumPropertyOfferType =
  | "OFFER_BUY" | "OFFER_RENT" | "OFFER_LIFE_ANNUITY_SALE"
  | "OFFER_HOLIDAYS" | "OFFER_AUCTION"
  | "OFFER_BUSINESS_TAKE_OVER" | "OFFER_LEASE_BACK" | "OFFER_UNKNOWN"

type EnumPropertyClass =
  | "CLASS_FLAT" | "CLASS_HOUSE" | "CLASS_PROGRAM" | "CLASS_LAND"
  | "CLASS_PARKING" | "CLASS_OFFICE" | "CLASS_SHOP" | "CLASS_PREMISES"
  | "CLASS_BUILDING" | "CLASS_ROOM" | "CLASS_OTHER" | "CLASS_UNKNOWN"

type EnumPropertyAlertMatch =
  | "ALERT_MATCH_CREATED"   // new property matched (safe default)
  | "ALERT_MATCH_MERGED"    // ONLY when a new advert is merged into an already-matched property (advanced, higher volume on large filters)

type EnumAdvertAlertMatch =
  | "ALERT_MATCH_CREATED"      // new advert matched
  | "ALERT_MATCH_ADVERT_EVENT" // PRICE/REPUBLISHED/UNPUBLISHED on previously-matched advert

type EnumSearchRequestSortBy =
  | "FIRST_SEEN_AT" | "LAST_SEEN_AT" | "LAST_UPDATED_AT" | "PRICE" | "RELEVANCE"
type EnumOrderBy = "ASC" | "DESC"

type EnumPricingScope = "PRICING_ONE_OFF" | "PRICING_MENSUAL"
type EnumCurrency     = "CURRENCY_EUR" | "CURRENCY_USD"
```

## 5. Hard limits & auth
- size: 1-100 (full search) or 1-25 (lite search)
- search.keywords / search.fullTexts: max 20 items each
- geoDistance.distanceKm > 0 (else 400)
- geoBoundingBox: topLeft.lat > bottomRight.lat AND topLeft.lon < bottomRight.lon
- API base: https://api.fluximmo.io
- Auth: header `x-api-key: <YOUR_KEY>` (get one at https://my.fluximmo.io, free 1-week trial)

## 6. Match types & events
- PROPERTIES alerts emit:
  - ALERT_MATCH_CREATED: a new property qualified
  - ALERT_MATCH_MERGED: ONLY when a new advert is merged into an already-matched property (not on every check)
- ADVERTS alerts emit (alerts only — no public adverts/search endpoint exists):
  - ALERT_MATCH_CREATED: new advert matched
  - ALERT_MATCH_ADVERT_EVENT: event on a previously matched advert. Event subtypes: PRICE (any change, even 1 EUR), REPUBLISHED (offline -> online), UNPUBLISHED (online -> offline). CHECK is never emitted.
- NO BACKFILL on alert creation: events apply only to items processed AFTER alert creation. PROPERTIES side: combine `search` (one-shot retrospective) + `alert` (continuous). ADVERTS side: ask Fluximmo to replay historical backfill on your webhook by mail to [email protected].
- DELETING + RECREATING an alert loses event history. Use `PATCH /alerts/{flxId}` to modify in place.

## 7. 8 validated archetypes (Phase 3 PASS, 2026-05-04)

### A1. PROPERTIES — Paris achat appartement standard combo
POST /v2/protected/properties/search
```json
{"size":25,"sortBy":"FIRST_SEEN_AT","orderBy":"DESC","search":{"filterProperty":{"location":[{"postalCode":"75001"}],"type":["CLASS_FLAT","CLASS_HOUSE","CLASS_PROGRAM"],"offer":[{"type":"OFFER_BUY"}],"price":{"initial":{"value":{"min":100000,"max":350000}}},"habitation":{"surface":{"total":{"min":30,"max":110}},"bedroomCount":{"min":1,"max":3}},"meta":{"isTotallyOffline":false}}}}
```

### A2. PROPERTIES — Dpt 13 location maison >=80m2 >=3ch
POST /v2/protected/properties/search
```json
{"size":25,"sortBy":"FIRST_SEEN_AT","orderBy":"DESC","search":{"filterProperty":{"location":[{"department":"13"}],"type":["CLASS_HOUSE"],"offer":[{"type":"OFFER_RENT"}],"habitation":{"surface":{"total":{"min":80}},"bedroomCount":{"min":3}},"meta":{"isTotallyOffline":false}}}}
```

### A3. PROPERTIES — geoDistance 20km Tour Eiffel
POST /v2/protected/properties/search
```json
{"size":25,"sortBy":"FIRST_SEEN_AT","orderBy":"DESC","search":{"filterProperty":{"location":[{"locationCoordinate":{"location":{"geoDistance":{"pin":{"lat":48.85837,"lon":2.294481},"distanceKm":20}}}}],"type":["CLASS_FLAT"],"offer":[{"type":"OFFER_BUY"}],"meta":{"isTotallyOffline":false}}}}
```

### A4. PROPERTIES — geoBoundingBox Paris
POST /v2/protected/properties/search
```json
{"size":25,"sortBy":"FIRST_SEEN_AT","orderBy":"DESC","search":{"filterProperty":{"location":[{"locationCoordinate":{"location":{"geoBoundingBox":{"topLeft":{"lat":48.9021,"lon":2.2241},"bottomRight":{"lat":48.8156,"lon":2.4699}}}}}],"offer":[{"type":"OFFER_BUY"}],"meta":{"isTotallyOffline":false}}}}
```

### A5. PROPERTIES — Multi-zones OR (Paris + petite couronne 75/92/93/94)
POST /v2/protected/properties/search
```json
{"size":25,"sortBy":"FIRST_SEEN_AT","orderBy":"DESC","search":{"filterProperty":{"location":[{"department":"75"},{"department":"92"},{"department":"93"},{"department":"94"}],"type":["CLASS_FLAT"],"offer":[{"type":"OFFER_BUY"}],"meta":{"isTotallyOffline":false}}}}
```

### A6. ADVERTS alert — Dpt 75 achat appartement (CREATED only)
PUT /v2/protected/adverts/search/alerts
```json
{"search_query":{"filterAd":{"location":{"department":"75"},"type":["CLASS_FLAT"],"offer":[{"type":"OFFER_BUY"}],"isOnline":true}},"webhook_url":"https://votre-domaine.com/webhooks/fluximmo","match":["ALERT_MATCH_CREATED"],"search_name":"Achat T2-T3 Paris"}
```

### A7. ADVERTS alert — With events (PRICE / REPUBLISHED / UNPUBLISHED)
PUT /v2/protected/adverts/search/alerts
```json
{"search_query":{"filterAd":{"location":{"department":"75"},"type":["CLASS_FLAT"],"offer":[{"type":"OFFER_BUY"}],"currentPrice":{"value":{"max":600000}},"isOnline":true}},"webhook_url":"https://votre-domaine.com/webhooks/fluximmo","match":["ALERT_MATCH_CREATED","ALERT_MATCH_ADVERT_EVENT"],"search_name":"Paris achat - veille prix"}
```

### A8. PROPERTIES alert — Combo standard match=[CREATED]
PUT /v2/protected/properties/search/alerts
```json
{"search_query":{"filterProperty":{"location":[{"postalCode":"75001"}],"type":["CLASS_FLAT"],"offer":[{"type":"OFFER_BUY"}],"meta":{"isTotallyOffline":false}}},"webhook_url":"https://votre-domaine.com/webhooks/fluximmo-properties","match":["ALERT_MATCH_CREATED"],"search_name":"Properties Paris achat appartement"}
```

## 8. Anti-patterns (read before generating)
- DO NOT confuse Property and Advert. Property = unique deduplicated asset (webhook = IDs only, refetch needed). Advert = one listing on one portal (webhook = full payload + events).
- DO NOT use `city` in FilterLocation: it is silently IGNORED. Use postalCode / inseeCode / department / irisCode.
- DO NOT use geoShape / POLYGON: not currently exposed. Use geoBoundingBox or geoDistance, optionally combined with multi-zone OR (array of FilterLocation entries).
- DO NOT mix GeoJSON `[lon, lat]` with API `{lat, lon}`: the API everywhere uses `{lat, lon}` objects, never arrays.
- DO NOT swap geoBoundingBox corners: topLeft.lat must be > bottomRight.lat AND topLeft.lon must be < bottomRight.lon.
- DO NOT confuse FilterPropertyPrice (`price.initial.value.{min,max}` / `price.latest.value.{min,max}`) with FilterAdvertPrice (`currentPrice.value.{min,max}` — different field name AND nested under `value`). They are not interchangeable.
- DO NOT rely on backfill at alert creation: alerts only match items processed AFTER creation. Combine search + alert.
- DO NOT delete + recreate an alert to modify it (loses event history). Use `PATCH /alerts/{flxId}`.
- DO NOT use Properties alerts to track per-listing price changes: PRICE / REPUBLISHED / UNPUBLISHED events only exist on Adverts alerts (`ALERT_MATCH_ADVERT_EVENT`).
- DO NOT skip `meta.isTotallyOffline`: production best practice is `meta.isTotallyOffline=false` to exclude completely offline items.
- DO NOT use `ALERT_MATCH_MERGED` casually on Properties alerts: it multiplies webhook volume. Default to `["ALERT_MATCH_CREATED"]`.

## 9. Links
- Full docs: https://doc.fluximmo.io
- Sample no-auth Property: https://api.fluximmo.io/v2/sample/properties
- Sample no-auth Advert:   https://api.fluximmo.io/v2/sample/adverts
- Sample webhook Property: https://api.fluximmo.io/v2/sample/webhook/properties
- Sample webhook Advert:   https://api.fluximmo.io/v2/sample/webhook/adverts
- Concepts: /concepts/property-vs-advert , /concepts/match-types-cycle-alerte , /concepts/recherche-geographique , /concepts/webhooks
- Free trial API key: https://my.fluximmo.io (1 week, no commercial calls)

Last updated: 2026-05-04
Token count target: 2000-4000 tokens (~5-10K chars)