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.
Base URL
https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-apiAuthentification
Toutes les requêtes (sauf /) doivent inclure un header Authorization au format HTTP Basic :
Authorization: Basic base64({site_id}:{api_token})Avec curl, utilisez simplement -u :
curl -u "11111111-2222-3333-4444-555555555555:flk_xxx..." \
"https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/11111111-2222-3333-4444-555555555555/properties"Limites & quotas
- 300 requêtes / minute / token par défaut (personnalisable). Au-delà :
429 Too Many RequestsavecRetry-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 :
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1761670920
Retry-After: 12 # présent uniquement sur 429Idempotence
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.
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) :
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 :
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.
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 :
{
"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
/agencies/{site_id}Récupérer l'agence
Retourne les informations publiques de votre agence (nom, contact, services).
Exemple cURL
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}" \
-u "{site_id}:{api_token}"Réponse 200
{
"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"
]
}/agencies/{site_id}/propertiesLister vos biens
Liste paginée des biens publiés via l'API par votre agence.
properties:readParamè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
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/properties" \
-u "{site_id}:{api_token}"Réponse 200
{
"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"
}
]
}/agencies/{site_id}/properties/{external_id}Détail d'un bien
Retourne un bien identifié par son external_id (votre référence interne).
properties:readExemple cURL
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
{
"external_id": "REF-1024",
"id": "uuid",
"title": "Appartement 3 chambres",
"description": "Lumineux, terrasse 20m²…",
"price": "650000",
"images": [
"https://…/photo1.jpg"
],
"status": "active"
}/agencies/{site_id}/propertiesCré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.
properties:writeCorps de la requête
{
"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
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
{
"external_id": "REF-1024",
"id": "uuid",
"public_url": "https://filia.lu/property/uuid",
"status": "active"
}/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.
properties:writeCorps de la requête
{
"title": "Appartement 3 chambres - prix baissé",
"price": 625000,
"status": "active"
}Exemple cURL
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
{
"external_id": "REF-1024",
"id": "uuid",
"price": "625000",
"status": "active"
}/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.
properties:writeExemple cURL
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
{
"deleted": true,
"external_id": "REF-1024"
}/agencies/{site_id}/contactsLister les leads
Récupère les contacts reçus sur vos biens (formulaire, demande de visite, estimation).
contacts:readParamètres de requête
limit (integer) — Nombre d'éléments (1-200, défaut 50)offset (integer) — Décalage de paginationExemple cURL
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/contacts" \
-u "{site_id}:{api_token}"Réponse 200
{
"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"
}
}
]
}/agencies/{site_id}/contacts/{id}Détail d'un lead
Retourne un lead unique avec toutes ses informations de qualification.
contacts:readExemple cURL
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/contacts/{id}" \
-u "{site_id}:{api_token}"Réponse 200
{
"id": "uuid",
"name": "Jean Dupont",
"email": "jean@exemple.lu",
"qualification_data": {
"budget": 700000,
"timeframe": "3 mois",
"is_first_buyer": false
}
}/agencies/{site_id}/stats/propertiesStatistiques 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.
stats:readParamè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 totalexternal_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
curl -X GET "https://scespkmzvykarrcwwqes.supabase.co/functions/v1/public-api/agencies/{site_id}/stats/properties" \
-u "{site_id}:{api_token}"Réponse 200
{
"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.
AscenseurCarportBuanderieDressingLocal vélosInterphoneVidéophoneConciergeClimatisationCaveGrenierBalconTerrasseLoggiaJardinVolets électriquesDouble vitrageTriple vitrageDomotiqueFibreAlarmeVidéo surveillanceDigicodeVMCPanneaux solairesPanneaux photovoltaïquesCheminée/PoêleCiterne eau de pluiePompe à chaleurPiscineSaunaSpaJardin communVitrineExtractionVentilationChambre froideRéserveCuisine professionnelleRideau métalliqueAccessibilité PMRSalles de réunionCuisine équipéeSanitaires privésOpen space modulableCafétériaDouchesFaux plancherFaux plafondContrôle d'accèsParking privéBornes recharge électriqueRestaurantBarRoom serviceRéception 24hConciergerieBlanchisserieNavetteSalle de fitnessTerrasse panoramiqueRooftopCoffre-fort chambresQuai de chargementTriphaséAccès poids lourdsMonte-chargePont roulantAire de retournementVentilation industrielleSprinklersClôture sécuriséeDétection incendieBureaux intégrésVestiairesRaccordement 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.
| Statut | Code | Signification |
|---|---|---|
| 400 | validation_error | Corps invalide (voir fields) |
| 400 | invalid_json | Body non parsable en JSON |
| 401 | missing_auth / invalid_token | Token absent, invalide ou révoqué |
| 401 | site_mismatch | site_id Basic ≠ token |
| 403 | forbidden | Scope insuffisant |
| 404 | not_found | Ressource introuvable |
| 409 | conflict | external_id déjà utilisé (utilisez PUT) |
| 409 | idempotency_conflict | Idempotency-Key réutilisée avec un autre body |
| 429 | rate_limited | Voir Retry-After |
| 500 | db_error | Erreur serveur — réessayez ou contactez le support |
{
"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é (headersX-RateLimit-*,Retry-After). SupportIdempotency-Keysur POST/PUT (24 h). Webhooks sortants HMAC-SHA256 (lead.created,property.status_changed) + CRUD dédié. EndpointsGET /healthetGET /openapi.json(OpenAPI 3.1). Pagination cursor sur/contacts. Mode sandbox. Erreurs normalisées avecdocs_urletfields.v1.1 · 2026-07-28Ajout des champs surfaces / bâtiment / énergie / équipements / disponibilité. EndpointGET /amenities/vocabulary. Bloc_normalization. HeaderX-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