Aller au contenu principal

API Filia v1

L'API Filia permet à votre CRM, ERP ou logiciel maison de publier des biens immobiliers sur filia.lu et de récupérer les leads en temps réel — exactement comme une intégration Apimo.

Publication temps réel
Les biens créés via l'API apparaissent immédiatement sur filia.lu.
Auth simple
HTTP Basic avec votre identifiant agence et un token généré dans le dashboard.
REST + JSON
Structure familière, identique aux conventions Apimo / Stripe.

Base URL

text
https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api

Authentification

Toutes les requêtes (sauf /) doivent inclure un header Authorization au format HTTP Basic :

http
Authorization: Basic base64({site_id}:{api_token})

Avec curl, utilisez simplement -u :

bash
curl -u "11111111-2222-3333-4444-555555555555:flk_xxx..." \
  "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/11111111-2222-3333-4444-555555555555/properties"
Obtenir une clé : connectez-vous à votre espace agence, ouvrez l'onglet API et cliquez sur Générer. Le token n'est affiché qu'une seule fois — stockez-le dans un coffre-fort sécurisé.

Limites & quotas

  • 300 requêtes / minute / token par défaut (personnalisable). Au-delà : 429 Too Many Requests avec Retry-After.
  • Body JSON max : 1 Mo. Pagination max : limit=200.
  • Jusqu'à 60 images, 10 vidéos, 10 visites virtuelles, 20 documents par bien.
  • Toutes les réponses incluent X-API-Version: v1.

Chaque réponse renvoie 3 headers pour piloter votre client :

http
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1761670920
Retry-After: 12   # présent uniquement sur 429

Idempotence

Sur POST et PUT, envoyez un header Idempotency-Key (UUID recommandé). En cas de retry réseau, la même clé + le même body renvoient la réponse mise en cache (24 h). Une clé réutilisée avec un body différent renvoie 409 idempotency_conflict.

bash
curl -X POST "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/properties" \
  -u "{site_id}:{api_token}" \
  -H "Idempotency-Key: 8f2c9d3e-1a4b-4d5f-9c8e-2b3a4d5e6f70" \
  -H "Content-Type: application/json" \
  -d '{ "external_id": "REF-1024", "title": "..." }'

Webhooks

Recevez les événements FILIA en temps réel sur votre URL. Deux événements v1 : lead.created (nouveau contact) et property.status_changed (changement de disponibilité).

Enregistrer un webhook (le signing_secret n'est renvoyé qu'une seule fois) :

bash
curl -X POST "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/webhooks" \
  -u "{site_id}:{api_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://crm.exemple.com/webhooks/filia",
    "events": ["lead.created","property.status_changed"],
    "description": "CRM prod"
  }'

Chaque livraison contient une signature HMAC-SHA256 à vérifier :

http
POST /webhooks/filia HTTP/1.1
X-Filia-Event: lead.created
X-Filia-Delivery-Id: b4f2e3a0-...
X-Filia-Timestamp: 1761670920
X-Filia-Signature: sha256=<hex>

{ "id":"...", "event":"lead.created", "delivered_at":"...", "data": { ... } }

Vérification : HMAC_SHA256(signing_secret, raw_body) doit correspondre à la partie hex du header X-Filia-Signature. Politique de retry : 3 tentatives (0 s, 0.5 s, 2 s). Timeout : 8 s. Renvoyez 2xx pour accuser réception.

Mode sandbox

Demandez un token sandbox pour tester votre intégration sans polluer la production. Les biens publiés avec un token sandbox sont stockés côté FILIA mais ne remontent jamais dans la recherche publique (statut forcé à inactive, flag _sandbox: true dans la réponse). Idéal pour valider un mapping avant mise en prod.

OpenAPI & santé

  • Spec OpenAPI 3.1 : GET https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/openapi.json — importable dans Postman, Insomnia, ou pour générer un SDK (openapi-generator, Speakeasy…).
  • Health check : GET https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/health — renvoie { status, version, db_latency_ms, timestamp }. Aucun auth requis.

Exemple complet — Publier un bien

Requête POST avec l'ensemble des champs supportés en v1 (surfaces, bâtiment, énergie, équipements normalisés, médias, documents, disponibilité). Copiez-collez, remplacez {site_id} / {api_token}, adaptez les valeurs.

bash
curl -X POST "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/properties" \
  -u "{site_id}:{api_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "REF-1024",
    "title": "Appartement 3 chambres - Belair",
    "description": "Lumineux appartement avec terrasse orientée sud-ouest...",
    "price": 650000,
    "price_hidden": false,
    "transaction_type": "sale",
    "property_type": "Appartement",
    "location": "Luxembourg-Belair",
    "latitude": 49.6116, "longitude": 6.1180,
    "bedrooms": 3, "bathrooms": 2, "parking": 1,
    "area": 95, "usable_area": 88, "land_area": 0,
    "floor": 2, "total_floors": 5,
    "construction_year": 2018, "renovation_year": 2024,
    "condition": "tres_bon", "furnished": false,
    "heating_type": "Pompe à chaleur", "ventilation": "Double flux",
    "energy_class": "B", "insulation_class": "B",
    "amenities": ["Ascenseur","Climatisation","Domotique","Fibre","Double vitrage","Volets électriques","Alarme","Vidéophone","Panneaux photovoltaïques","Cave","Balcon"],
    "amenities_raw": ["Store banne motorisé","Borne de recharge 22 kW"],
    "availability_state": "available",
    "availability_date": "2026-09-01",
    "images": ["https://cdn.exemple.com/p1.jpg","https://cdn.exemple.com/p2.jpg"],
    "videos": ["https://youtu.be/dQw4w9WgXcQ"],
    "virtual_tours": ["https://my.matterport.com/show/?m=XXXX"],
    "documents": [{"url":"https://cdn.exemple.com/passeport.pdf","label":"Passeport énergétique"}],
    "source_url": "https://crm.exemple.com/biens/1024",
    "status": "active"
  }'

La réponse 201 contient un bloc _normalization :

json
{
  "external_id": "REF-1024",
  "id": "uuid",
  "public_url": "https://filia.lu/property/uuid",
  "status": "active",
  "_normalization": {
    "amenities_normalized": ["Ascenseur","Climatisation","Domotique","Fibre","Double vitrage","Volets électriques","Alarme","Vidéophone","Panneaux photovoltaïques","Cave","Balcon"],
    "amenities_unknown": []
  }
}

Les valeurs reconnues remontent dans les filtres publics FILIA. Les valeurs non reconnues (amenities_unknown) sont conservées dans amenities_raw et affichées sur la fiche du bien.

💡 Récupérer la liste officielle en JSON : GET https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/amenities/vocabulary (endpoint public, sans auth).

Endpoints

GET/agencies/{site_id}

Récupérer l'agence

Retourne les informations publiques de votre agence (nom, contact, services).

Exemple cURL

bash
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}" \
  -u "{site_id}:{api_token}"

Réponse 200

json
{
  "id": "11111111-2222-3333-4444-555555555555",
  "name": "Agence Démo",
  "email": "contact@agence-demo.lu",
  "phone": "+352 20 12 34 56",
  "address": "12 rue de la Gare, L-1234 Luxembourg",
  "languages": [
    "fr",
    "en",
    "lu"
  ],
  "services": [
    "sale",
    "rental",
    "estimation"
  ]
}
GET/agencies/{site_id}/properties

Lister vos biens

Liste paginée des biens publiés via l'API par votre agence.

scope requis : properties:read

Paramètres de requête

limit (integer) — Nombre d'éléments (1-200, défaut 50)
offset (integer) — Décalage de pagination (défaut 0)

Exemple cURL

bash
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/properties" \
  -u "{site_id}:{api_token}"

Réponse 200

json
{
  "total": 124,
  "limit": 50,
  "offset": 0,
  "items": [
    {
      "external_id": "REF-1024",
      "id": "uuid",
      "title": "Appartement 3 chambres - Belair",
      "price": "650000",
      "transaction_type": "sale",
      "property_type": "Appartement",
      "bedrooms": 3,
      "area": "95",
      "status": "active",
      "public_url": "https://filia.lu/property/uuid"
    }
  ]
}
GET/agencies/{site_id}/properties/{external_id}

Détail d'un bien

Retourne un bien identifié par son external_id (votre référence interne).

scope requis : properties:read

Exemple cURL

bash
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/properties/{external_id}" \
  -u "{site_id}:{api_token}"

Réponse 200

json
{
  "external_id": "REF-1024",
  "id": "uuid",
  "title": "Appartement 3 chambres",
  "description": "Lumineux, terrasse 20m²…",
  "price": "650000",
  "images": [
    "https://…/photo1.jpg"
  ],
  "status": "active"
}
POST/agencies/{site_id}/properties

Créer un bien

Publie un nouveau bien. L'external_id doit être unique pour votre agence. Le bien apparaît immédiatement sur filia.lu.

scope requis : properties:write

Corps de la requête

json
{
  "external_id": "REF-1024",
  "title": "Appartement 3 chambres - Belair",
  "description": "Lumineux appartement avec terrasse...",
  "price": 650000,
  "transaction_type": "sale",
  "property_type": "Appartement",
  "location": "Luxembourg-Belair",
  "latitude": 49.6116,
  "longitude": 6.118,
  "bedrooms": 3,
  "bathrooms": 2,
  "area": 95,
  "land_area": 0,
  "parking": 1,
  "floor": 2,
  "total_floors": 5,
  "construction_year": 2018,
  "renovation_year": 2024,
  "condition": "tres_bon",
  "furnished": false,
  "heating_type": "Pompe à chaleur",
  "ventilation": "Double flux",
  "energy_class": "B",
  "insulation_class": "B",
  "amenities": [
    "Ascenseur",
    "Climatisation",
    "Domotique",
    "Fibre",
    "Double vitrage",
    "Volets électriques",
    "Alarme",
    "Vidéophone",
    "Panneaux photovoltaïques",
    "Cave",
    "Balcon"
  ],
  "amenities_raw": [
    "Store banne motorisé",
    "Borne de recharge 22 kW"
  ],
  "availability_state": "available",
  "availability_date": "2026-09-01",
  "images": [
    "https://cdn.exemple.com/photo1.jpg",
    "https://cdn.exemple.com/photo2.jpg"
  ],
  "videos": [
    "https://youtu.be/dQw4w9WgXcQ"
  ],
  "virtual_tours": [
    "https://my.matterport.com/show/?m=XXXX"
  ],
  "documents": [
    {
      "url": "https://cdn.exemple.com/passeport-energetique.pdf",
      "label": "Passeport énergétique"
    }
  ],
  "source_url": "https://crm.exemple.com/biens/1024",
  "status": "active"
}

Exemple cURL

bash
curl -X POST "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/properties" \
  -u "{site_id}:{api_token}" \
  -H "Content-Type: application/json" \
  -d '{
  "external_id": "REF-1024",
  "title": "Appartement 3 chambres - Belair",
  "description": "Lumineux appartement avec terrasse...",
  "price": 650000,
  "transaction_type": "sale",
  "property_type": "Appartement",
  "location": "Luxembourg-Belair",
  "latitude": 49.6116,
  "longitude": 6.118,
  "bedrooms": 3,
  "bathrooms": 2,
  "area": 95,
  "land_area": 0,
  "parking": 1,
  "floor": 2,
  "total_floors": 5,
  "construction_year": 2018,
  "renovation_year": 2024,
  "condition": "tres_bon",
  "furnished": false,
  "heating_type": "Pompe à chaleur",
  "ventilation": "Double flux",
  "energy_class": "B",
  "insulation_class": "B",
  "amenities": [
    "Ascenseur",
    "Climatisation",
    "Domotique",
    "Fibre",
    "Double vitrage",
    "Volets électriques",
    "Alarme",
    "Vidéophone",
    "Panneaux photovoltaïques",
    "Cave",
    "Balcon"
  ],
  "amenities_raw": [
    "Store banne motorisé",
    "Borne de recharge 22 kW"
  ],
  "availability_state": "available",
  "availability_date": "2026-09-01",
  "images": [
    "https://cdn.exemple.com/photo1.jpg",
    "https://cdn.exemple.com/photo2.jpg"
  ],
  "videos": [
    "https://youtu.be/dQw4w9WgXcQ"
  ],
  "virtual_tours": [
    "https://my.matterport.com/show/?m=XXXX"
  ],
  "documents": [
    {
      "url": "https://cdn.exemple.com/passeport-energetique.pdf",
      "label": "Passeport énergétique"
    }
  ],
  "source_url": "https://crm.exemple.com/biens/1024",
  "status": "active"
}'

Réponse 201

json
{
  "external_id": "REF-1024",
  "id": "uuid",
  "public_url": "https://filia.lu/property/uuid",
  "status": "active"
}
PUT/agencies/{site_id}/properties/{external_id}

Mettre à jour un bien

Met à jour tous les champs du bien (remplacement complet). Utilisez le même external_id.

scope requis : properties:write

Corps de la requête

json
{
  "title": "Appartement 3 chambres - prix baissé",
  "price": 625000,
  "status": "active"
}

Exemple cURL

bash
curl -X PUT "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/properties/{external_id}" \
  -u "{site_id}:{api_token}" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Appartement 3 chambres - prix baissé",
  "price": 625000,
  "status": "active"
}'

Réponse 200

json
{
  "external_id": "REF-1024",
  "id": "uuid",
  "price": "625000",
  "status": "active"
}
DELETE/agencies/{site_id}/properties/{external_id}

Retirer un bien

Passe le statut du bien en inactive. Le bien n'apparaît plus dans les résultats publics.

scope requis : properties:write

Exemple cURL

bash
curl -X DELETE "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/properties/{external_id}" \
  -u "{site_id}:{api_token}"

Réponse 200

json
{
  "deleted": true,
  "external_id": "REF-1024"
}
GET/agencies/{site_id}/contacts

Lister les leads

Récupère les contacts reçus sur vos biens (formulaire, demande de visite, estimation).

scope requis : contacts:read

Paramètres de requête

limit (integer) — Nombre d'éléments (1-200, défaut 50)
offset (integer) — Décalage de pagination

Exemple cURL

bash
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/contacts" \
  -u "{site_id}:{api_token}"

Réponse 200

json
{
  "total": 12,
  "limit": 50,
  "offset": 0,
  "items": [
    {
      "id": "uuid",
      "name": "Jean Dupont",
      "email": "jean@exemple.lu",
      "phone": "+352 661 12 34 56",
      "message": "Je souhaite visiter ce bien",
      "financing": "cash",
      "created_at": "2026-06-03T10:23:00Z",
      "property": {
        "id": "uuid",
        "external_id": "REF-1024",
        "title": "Appartement 3 chambres"
      }
    }
  ]
}
GET/agencies/{site_id}/contacts/{id}

Détail d'un lead

Retourne un lead unique avec toutes ses informations de qualification.

scope requis : contacts:read

Exemple cURL

bash
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/contacts/{id}" \
  -u "{site_id}:{api_token}"

Réponse 200

json
{
  "id": "uuid",
  "name": "Jean Dupont",
  "email": "jean@exemple.lu",
  "qualification_data": {
    "budget": 700000,
    "timeframe": "3 mois",
    "is_first_buyer": false
  }
}
GET/agencies/{site_id}/stats/properties

Statistiques par annonce et par jour

Compteurs de consultation et de leads pour chacun de vos biens : vues, visiteurs uniques, demandes de contact et conversations. Uniquement des compteurs agrégés — aucune donnée personnelle de prospect n'est exposée.

scope requis : stats:read

Paramètres de requête

from (date) — Jour de début YYYY-MM-DD (défaut : J-30)
to (date) — Jour de fin YYYY-MM-DD (défaut : aujourd'hui)
granularity (string) — day (défaut) ou total
external_id (string) — Limiter à une seule annonce (votre référence)
limit (integer) — Nombre d'annonces (1-500, défaut 200)
offset (integer) — Décalage de pagination (défaut 0)

Exemple cURL

bash
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/stats/properties" \
  -u "{site_id}:{api_token}"

Réponse 200

json
{
  "version": "v1",
  "site_id": "uuid",
  "from": "2026-07-27",
  "to": "2026-08-25",
  "granularity": "day",
  "totals": {
    "views": 125,
    "unique_viewers": 98,
    "contacts": 0,
    "conversations": 0
  },
  "total_properties": 29,
  "limit": 200,
  "offset": 0,
  "items": [
    {
      "external_id": "REF-1024",
      "property_id": "uuid",
      "days": [
        {
          "date": "2026-08-24",
          "views": 3,
          "unique_viewers": 3,
          "contacts": 0,
          "conversations": 0
        },
        {
          "date": "2026-08-25",
          "views": 1,
          "unique_viewers": 1,
          "contacts": 1,
          "conversations": 0
        }
      ],
      "totals": {
        "views": 4,
        "unique_viewers": 4,
        "contacts": 1,
        "conversations": 0
      }
    }
  ]
}

Vocabulaire équipements / prestations

Les champs amenities (tableau de chaînes) et amenities_raw (fallback texte libre) acceptent le vocabulaire ci-dessous. Les valeurs sont insensibles à la casse et aux accents côté FILIA : « ascenseur », « Ascenseur » et « ASCENSEUR » sont normalisées à la même valeur. Toute valeur non reconnue est conservée telle quelle dans amenities_raw — rien n'est perdu.

Résidentiel — Confort
AscenseurCarportBuanderieDressingLocal vélosInterphoneVidéophoneConciergeClimatisationCaveGrenierBalconTerrasseLoggiaJardin
Résidentiel — Technique
Volets électriquesDouble vitrageTriple vitrageDomotiqueFibreAlarmeVidéo surveillanceDigicodeVMCPanneaux solairesPanneaux photovoltaïquesCheminée/PoêleCiterne eau de pluiePompe à chaleur
Résidentiel — Loisirs
PiscineSaunaSpaJardin commun
Commerce
VitrineExtractionVentilationChambre froideRéserveCuisine professionnelleRideau métalliqueAccessibilité PMR
Bureau
Salles de réunionCuisine équipéeSanitaires privésOpen space modulableCafétériaDouchesFaux plancherFaux plafondContrôle d'accèsParking privéBornes recharge électrique
Hôtel
RestaurantBarRoom serviceRéception 24hConciergerieBlanchisserieNavetteSalle de fitnessTerrasse panoramiqueRooftopCoffre-fort chambres
Industriel
Quai de chargementTriphaséAccès poids lourdsMonte-chargePont roulantAire de retournementVentilation industrielleSprinklersClôture sécuriséeDétection incendieBureaux intégrésVestiaires
Terrain
Raccordement eauRaccordement électricitéRaccordement gazÉgoutsFibreTerrain platTerrain en penteAccès goudronnéClôturéViabilisé

Astuce : envoyez tout votre vocabulaire équipements dans amenities — FILIA remonte automatiquement les valeurs reconnues dans les filtres publics et conserve le reste dans amenities_raw pour affichage textuel sur la fiche.

Codes d'erreur

Toutes les erreurs suivent : { error: { code, message, field?, fields?, docs_url } }. Le champ docs_url pointe vers la section correspondante.

StatutCodeSignification
400validation_errorCorps invalide (voir fields)
400invalid_jsonBody non parsable en JSON
401missing_auth / invalid_tokenToken absent, invalide ou révoqué
401site_mismatchsite_id Basic ≠ token
403forbiddenScope insuffisant
404not_foundRessource introuvable
409conflictexternal_id déjà utilisé (utilisez PUT)
409idempotency_conflictIdempotency-Key réutilisée avec un autre body
429rate_limitedVoir Retry-After
500db_errorErreur serveur — réessayez ou contactez le support
json
{
  "error": {
    "code": "validation_error",
    "message": "One or more fields are invalid",
    "fields": { "price": ["Expected number, received string"] },
    "docs_url": "https://filia.lu/api/docs#errors"
  }
}

Changelog

  • v1.2 · 2026-07-28Rate limiting documenté (headers X-RateLimit-*, Retry-After). Support Idempotency-Key sur POST/PUT (24 h). Webhooks sortants HMAC-SHA256 (lead.created, property.status_changed) + CRUD dédié. Endpoints GET /health et GET /openapi.json (OpenAPI 3.1). Pagination cursor sur /contacts. Mode sandbox. Erreurs normalisées avec docs_url et fields.
  • v1.1 · 2026-07-28Ajout des champs surfaces / bâtiment / énergie / équipements / disponibilité. Endpoint GET /amenities/vocabulary. Bloc _normalization. Header X-API-Version.
  • v1.0 · 2026-05Version initiale : endpoints agences, biens (CRUD), leads (lecture). Auth HTTP Basic avec scopes.

Une question, un bug ?

Écrivez-nous, on répond dans la journée.

Contacter l'équipe Filia