Ideal House
Aller au contenu principal

Documentation de l'API de génération de plans d'étage#

URL de base : https://api.ideal.house
Version : v1
Mis à jour : 2026-08-09


📖 Vue d'ensemble#

L'API de génération de plans d'étage crée un plan d'étage résidentiel conceptuel en noir et blanc, vu de dessus, style CAO, généré par IA, à partir de besoins structurés en pièces et d'une invite personnalisée ou d'une image de référence optionnelle.

La sortie est destinée à l'exploration précoce de l'agencement. Il ne s'agit pas d'un plan de construction, et les dimensions, la géométrie, le placement des équipements et la conformité aux codes générés doivent être examinés par un professionnel qualifié.

Le flux de travail est asynchrone :

  1. Créer une tâche — Soumettez les paramètres du plan d'étage et recevez un taskId.
  2. Interrogation périodique des résultats — Interrogez le point de terminaison des résultats avec le taskId jusqu'à ce que la tâche atteigne un statut terminal.

🔐 Authentification#

Toutes les requêtes de l'API publique doivent inclure une clé API.

En-têteObligatoireValeur
APIKEY✅ OuiVotre clé API
Content-Type✅ Oui pour POSTapplication/json

[!WARNING] Gardez votre clé API en sécurité. Ne l'exposez pas dans le code côté client ou dans les dépôts publics.


💰 Déduction de crédits#

Les crédits sont déduits après la création réussie d'une tâche de génération. Si la tâche échoue finalement, les crédits déduits sont automatiquement remboursés. Des crédits insuffisants retournent le code d'erreur 9051.

Modèle (modelType)Taille de sortieCrédits
Base1536 × 102410
Pro2496 × 166420

Flash n'est pas pris en charge par l'API de plans d'étage.

Voir Référence de Déduction de Crédits pour le comportement de facturation courant.


📌 Points de terminaison de l'API#

1. Créer une Tâche de Plan d'Étage#

Crée une tâche de génération de plan d'étage et renvoie un ID de tâche unique.

Point de terminaison

http
POST /api/v1/floorPlan/generate

En-têtes de requête

En-têteRequisDescription
APIKEY✅ OuiClé d'authentification API
Content-Type✅ OuiDoit être application/json

Corps de la requête#

ChampTypeObligatoireDescriptionDéfaut
bedroomsinteger❌ NonNombre de chambres de 0 à 52
bathroomsnumber❌ NonNombre total de salles de bains de 0.5 à 4, par incréments de 0.51.5
totalAreastring✅ OuiSurface totale cible positive avec unité ou ft², comme 220 m² ou 1386 ft²
bedroomAreaRangesarray<object>❌ NonConseils de dimensionnement des chambres facultatifs. Voir Plages de Surface de ChambreDéduit de totalArea lorsqu'omis
bathroomDetailsobject❌ NonPréférences pour les salles de bains complètes uniquement. Voir Détails Salle de Bains
kitchenDetailsobject❌ NonConfiguration de cuisine facultative. Voir Détails Cuisine
keyRoomsarray<string>❌ NonPièces ou espaces supplémentaires. Voir Pièces Clés[]
promptstring❌ NonPriorités d'agencement supplémentaires. Cela ne peut pas remplacer les nombres définis par les champs structurés ou les contraintes visuelles rigides""
refImageUrlstring❌ NonURL d'une image de référence accessible publiquement""
modelTypestring❌ NonEnum : Base, ProBase

[!IMPORTANT] L'API publique valide actuellement bedrooms comme 0–5 et bathrooms comme 0.5–4. Les valeurs disponibles dans une autre interface cliente n'élargissent pas ces limites côté serveur.

Règles générales de requête#

  • Toutes les valeurs enum sont sensibles à la casse et doivent utiliser les valeurs anglaises affichées dans ce document.
  • totalArea est une surface totale cible utilisée pour guider l'échelle et les proportions ; elle n'est pas traitée comme une dimension de construction exacte.
  • L'invite personnalisée effective est limitée aux 800 premiers caractères lorsque l'invite d'image structurée est assemblée.
  • Les champs structurés ont la priorité sur les instructions contradictoires dans prompt.
  • Une tâche réussie génère exactement une image.

📐 Surface Totale#

totalArea contient une valeur numérique positive unique suivie d'une unité de surface.

UnitéExemple
220 m²
ft²1386 ft²

Un espace blanc avant l'unité est recommandé. Les valeurs décimales sont acceptées lorsqu'elles sont positives.

Exemples valides :

json
{
  "totalArea": "200 m²"
}
json
{
  "totalArea": "1850 ft²"
}

🛏️ Plages de Surface de Chambre#

bedroomAreaRanges fournit des conseils de dimensionnement relatif des chambres. Il ne demande pas d'étiquettes de surface numérique dans l'image générée.

Chaque élément a la forme suivante :

ChampTypeRequisDescription
namestring❌ NonIdentité de la chambre, par exemple Room 1 (Master) ou Room 2
minAreastring❌ NonSurface minimale positive
maxAreastring❌ NonSurface maximale positive ; ne peut pas être inférieure à minArea
unitstring❌ NonEnum : , ft² ; utilisez la même unité que totalArea

Exemple de plage explicite

json
{
  "bedroomAreaRanges": [
    {
      "name": "Room 1 (Master)",
      "minArea": "30",
      "maxArea": "40",
      "unit": "m²"
    },
    {
      "name": "Room 2",
      "minArea": "20",
      "maxArea": "30",
      "unit": "m²"
    }
  ]
}

Règles lorsqu'un tableau non vide est fourni :

  • Sa longueur doit être égale à bedrooms.
  • Chaque minArea et maxArea fourni doit être une chaîne numérique positive.
  • Lorsque les deux valeurs sont fournies, minArea <= maxArea.
  • unit, lorsqu'il est fourni, doit être ou ft².
  • Les noms sont conservés. Les éléments vides ou nuls ne fournissent pas de conseils de dimensionnement.

Plages automatiques lorsqu'omis#

Le champ peut être omis ou envoyé comme un tableau vide. Lorsqu'aucun élément ne contient de minArea ou maxArea effectif, le chemin de génération structuré déduit des plages internes de chambres à partir de totalArea et bedrooms :

  • Le budget de surface des chambres commence à 20% de la surface totale pour une chambre.
  • Le budget augmente de 7.5 points de pourcentage pour chaque chambre supplémentaire, plafonné à 50%.
  • La première chambre reçoit un coefficient de dimensionnement de 1.3 ; chaque autre chambre reçoit un coefficient de 1.0.
  • Chaque cible devient une plage approximative de ±10%, arrondie à des unités de surface entières.
  • L'unité est héritée de totalArea.
  • Les noms de pièces non vides existants sont conservés ; sinon, le serveur utilise Room 1, Room 2, etc.

Pour 200 m² et 4 chambres, les conseils déduits actuels sont approximativement :

json
[
  { "name": "Room 1", "minArea": "23", "maxArea": "28", "unit": "m²" },
  { "name": "Room 2", "minArea": "18", "maxArea": "22", "unit": "m²" },
  { "name": "Room 3", "minArea": "18", "maxArea": "22", "unit": "m²" },
  { "name": "Room 4", "minArea": "18", "maxArea": "22", "unit": "m²" }
]

Ces valeurs sont des conseils proportionnels internes, pas des surfaces finales de pièce garanties. Les plages explicites valides ont toujours la priorité sur les plages automatiques.

Lorsque bedrooms est 0, omettez bedroomAreaRanges ou envoyez [].


🛁 Détails Salle de Bains#

bathrooms représente le nombre total de salles de bains :

  • Sa partie entière est le nombre de salles de bains complètes.
  • Une fraction .5 ajoute une demi-salle de bains.
  • Chaque salle de bains complète est invitée à inclure des toilettes, un meuble vasque/lavabo et une douche ou zone humide.
  • Une demi-salle de bains contient des toilettes et un meuble vasque/lavabo uniquement, sans douche ni baignoire.

bathroomDetails configure uniquement les salles de bains complètes :

json
{
  "bathroomDetails": {
    "fullBathroomOptions": [
      {
        "name": "Bathroom 1",
        "wetDrySeparation": "yes",
        "bathtub": "required"
      },
      {
        "name": "Bathroom 2",
        "wetDrySeparation": "no",
        "bathtub": "optional"
      }
    ]
  }
}
ChampTypeValeurs autoriséesDescription
namestringBathroom 1, Bathroom 2, etc.Identité d'affichage optionnelle
wetDrySeparationstring / nullyes, no, nullIndique s'il faut afficher une zone humide séparée
bathtubstring / nullno, optional, required, nullPréférence de baignoire

Règles :

  • fullBathroomOptions.length ne peut pas dépasser floor(bathrooms).
  • Le tableau peut contenir uniquement les salles de bains complètes pour lesquelles des préférences ont été sélectionnées.
  • Une valeur null signifie non spécifiée.
  • Une baignoire requise est supplémentaire par rapport aux équipements standard de salle de bains complète ; elle ne remplace pas les toilettes ni la douche.
  • La séparation humide/sec est une cloison interne dans une salle de bains comptée, pas une salle de bains supplémentaire.

🍳 Détails Cuisine#

Tous les sous-champs de kitchenDetails sont facultatifs. Omettez l'objet entier lorsqu'aucune préférence de cuisine n'est sélectionnée.

json
{
  "kitchenDetails": {
    "type": "open",
    "size": "standard",
    "layout": "U",
    "islandType": "preparation",
    "storage": "maximum",
    "features": ["breakfast nook", "pantry"]
  }
}
ChampTypeValeurs autorisées
typestringopen, semi-open, closed
sizestringsmall, standard, large, extra large
layoutstringI, L, U, gallery
islandTypestringno, preparation, cooking, entertainment
storagestringminimal, standard, maximum
featuresarray<string>eating bar, breakfast nook, pantry

Une configuration partielle est valide. Par exemple :

json
{
  "kitchenDetails": {
    "type": "semi-open"
  }
}

🚪 Pièces Clés#

keyRooms accepte un tableau de ces valeurs exactes :

ValeurDescription
walk-in closetPièce-penderie dédiée reliée à une chambre
laundry roomEspace buanderie dédié
storage roomPièce de rangement général
utility roomPièce technique ou de service
home officeBureau ou cabinet dédié
garageGarage avec ouverture extérieure pour véhicule et accès intérieur à la maison
pantryGarde-manger adjacent à la cuisine
combined living-diningUne zone salon et salle à manger combinée
balconyBalcon extérieur connecté à l'espace de vie ou à une chambre principale

La valeur Web héritée balcon est également acceptée et normalisée en balcony.

Règles :

  • Les valeurs vides sont ignorées et les valeurs en double sont supprimées.
  • Les pièces clés sélectionnées sont demandées une seule fois.
  • Les espaces optionnels non sélectionnés sont exclus du programme de pièce généré.
  • Si pantry apparaît à la fois dans kitchenDetails.features et keyRooms, un seul garde-manger est demandé.

Exemple :

json
{
  "keyRooms": [
    "garage",
    "home office",
    "combined living-dining"
  ]
}

🖼️ Image de Référence#

refImageUrl est facultatif et doit être directement accessible par le serveur API.

Conditions requises :

  • Format : JPG/JPEG, PNG ou WebP.
  • Taille maximale du fichier : 20 Mo.
  • Dimensions minimales : 128 × 128 px.
  • Dimensions maximales : 6,000 × 6,000 px. Les images plus grandes sont redimensionnées de manière proportionnelle avant traitement.

L'image de référence guide l'agencement, l'adjacence, les proportions ou le style visuel. Elle ne remplace pas les nombres de pièces définis par les champs structurés ou d'autres contraintes rigides.


🤖 Types de Modèle#

ValeurDescription
BaseDéfaut. Qualité de génération équilibrée, sortie 1536 × 1024
ProSortie plus haute résolution 2496 × 1664 avec un temps de génération plus long attendu

Seuls Base et Pro sont pris en charge.


Champs non présents dans le contrat fonctionnel public#

Les champs suivants ne doivent pas être utilisés par les clients de l'API publique :

ChampRemarques
imageNumbersLe générateur actuel retourne toujours une image ; ce champ n'est pas nécessaire
extDataMétadonnées internes de suivi de groupe de tâches Web ; les clients publics doivent l'omettre
isApiCallDéterminé par le point de terminaison de l'API, pas par le corps de la requête
genByMemberMétadonnées de génération internes, pas un champ de requête de Plan d'Étage

Champs hérités supprimés qui ne doivent pas être envoyés :

text
floorplanSetting
roomCounts
grossArea
totalAreaValue
totalAreaUnit
totalAreaType
fullBathrooms
halfBathrooms
halfBathroomRequirement
kitchenType
diningRooms
livingRooms
extras
referenceImage
hasDetailOptions

📥 Exemples de Création de Tâche#

Requête minimale avec plages de chambres automatiques#

bash
curl -X POST "https://api.ideal.house/api/v1/floorPlan/generate" \
  -H "APIKEY: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "bedrooms": 4,
    "bathrooms": 2,
    "totalArea": "200 m²",
    "modelType": "Pro",
    "prompt": "Upper floor of a two-story Saudi Arabian villa with a master bedroom, family living area, staircase landing, and balcony"
  }'

Requête complète#

cURL
bash
curl -X POST "https://api.ideal.house/api/v1/floorPlan/generate" \
  -H "APIKEY: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "bedrooms": 3,
    "bathrooms": 2.5,
    "totalArea": "220 m²",
    "bedroomAreaRanges": [
      {"name": "Room 1 (Master)", "minArea": "30", "maxArea": "40", "unit": "m²"},
      {"name": "Room 2", "minArea": "20", "maxArea": "30", "unit": "m²"},
      {"name": "Room 3", "minArea": "20", "maxArea": "30", "unit": "m²"}
    ],
    "bathroomDetails": {
      "fullBathroomOptions": [
        {"name": "Bathroom 1", "wetDrySeparation": "yes", "bathtub": "required"},
        {"name": "Bathroom 2", "wetDrySeparation": "no", "bathtub": "optional"}
      ]
    },
    "kitchenDetails": {
      "type": "open",
      "size": "standard",
      "layout": "U",
      "islandType": "preparation",
      "storage": "maximum",
      "features": ["breakfast nook", "pantry"]
    },
    "keyRooms": ["garage", "home office", "combined living-dining"],
    "prompt": "Bright modern home with good natural lighting",
    "refImageUrl": "https://example.com/reference-plan.png",
    "modelType": "Pro"
  }'
Java (OkHttp)
java
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class FloorPlanApiExample {

    private static final String BASE_URL = "https://api.ideal.house";
    private static final String API_KEY = "your_api_key_here";

    public static void main(String[] args) throws Exception {
        OkHttpClient client = new OkHttpClient();
        String json = """
                {
                  "bedrooms": 4,
                  "bathrooms": 2,
                  "totalArea": "200 m²",
                  "keyRooms": ["walk-in closet", "balcony"],
                  "prompt": "Upper floor with a master bedroom and family living area",
                  "modelType": "Pro"
                }
                """;

        Request request = new Request.Builder()
                .url(BASE_URL + "/api/v1/floorPlan/generate")
                .addHeader("APIKEY", API_KEY)
                .addHeader("Content-Type", "application/json")
                .post(RequestBody.create(json, MediaType.parse("application/json")))
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}
Python (requests)
python
import requests

BASE_URL = "https://api.ideal.house"
API_KEY = "your_api_key_here"

payload = {
    "bedrooms": 4,
    "bathrooms": 2,
    "totalArea": "200 m²",
    "keyRooms": ["walk-in closet", "balcony"],
    "prompt": "Upper floor with a master bedroom and family living area",
    "modelType": "Pro",
}

response = requests.post(
    f"{BASE_URL}/api/v1/floorPlan/generate",
    headers={"APIKEY": API_KEY, "Content-Type": "application/json"},
    json=payload,
)
response.raise_for_status()
print("Task ID:", response.json()["data"])
Node.js (axios)
javascript
const axios = require('axios');

const BASE_URL = 'https://api.ideal.house';
const API_KEY = 'your_api_key_here';

async function createFloorPlanTask() {
  const response = await axios.post(
    `${BASE_URL}/api/v1/floorPlan/generate`,
    {
      bedrooms: 4,
      bathrooms: 2,
      totalArea: '200 m²',
      keyRooms: ['walk-in closet', 'balcony'],
      prompt: 'Upper floor with a master bedroom and family living area',
      modelType: 'Pro'
    },
    {
      headers: {
        APIKEY: API_KEY,
        'Content-Type': 'application/json'
      }
    }
  );

  console.log('Task ID:', response.data.data);
  return response.data.data;
}

createFloorPlanTask();

Réponse de succès de création de tâche#

json
{
  "code": 0,
  "message": "success",
  "data": 1234567890123456789
}
ChampTypeDescription
codeinteger0 indique que la tâche a été créée avec succès
messagestringMessage de réponse
datalongID de tâche utilisé pour interroger le point de terminaison des résultats

2. Obtenir le résultat de la tâche#

Retourne l'avancement de la tâche et l'image générée lorsqu'elle est disponible.

Point de terminaison

http
GET /api/v1/floorPlan/result?taskId={taskId}

En-têtes de requête

En-têteRequisDescription
APIKEY✅ OuiClé d'authentification API

Paramètres de requête

ParamètreTypeRequisDescription
taskIdlong✅ OuiID de tâche retourné par le point de terminaison de création

Exemples de requête de résultat#

cURL
bash
curl -X GET "https://api.ideal.house/api/v1/floorPlan/result?taskId=1234567890123456789" \
  -H "APIKEY: your_api_key_here"
Python interrogation
python
import time
import requests

BASE_URL = "https://api.ideal.house"
API_KEY = "your_api_key_here"
task_id = 1234567890123456789

while True:
    response = requests.get(
        f"{BASE_URL}/api/v1/floorPlan/result",
        headers={"APIKEY": API_KEY},
        params={"taskId": task_id},
    )
    response.raise_for_status()
    task = response.json()["data"]
    print(task["status"], task["percentage"], task["waitNumber"])

    if task["status"] in ("Success", "Failed", "Termination"):
        break

    time.sleep(3)

if task["status"] == "Success":
    print("Result URL:", task["output"]["resultUrl"])
Node.js interrogation
javascript
const axios = require('axios');

const BASE_URL = 'https://api.ideal.house';
const API_KEY = 'your_api_key_here';

async function pollFloorPlanResult(taskId) {
  while (true) {
    const response = await axios.get(
      `${BASE_URL}/api/v1/floorPlan/result`,
      {
        headers: { APIKEY: API_KEY },
        params: { taskId }
      }
    );

    const task = response.data.data;
    console.log(task.status, task.percentage, task.waitNumber);

    if (['Success', 'Failed', 'Termination'].includes(task.status)) {
      if (task.status === 'Success') {
        console.log('Result URL:', task.output.resultUrl);
      }
      return task;
    }

    await new Promise(resolve => setTimeout(resolve, 3000));
  }
}

pollFloorPlanResult('1234567890123456789');

Réponse de tâche terminée#

json
{
  "code": 0,
  "message": "success",
  "data": {
    "id": 1234567890123456789,
    "status": "Success",
    "waitNumber": 0,
    "percentage": 100,
    "input": {
      "bedrooms": 4,
      "bathrooms": 2,
      "totalArea": "200 m²",
      "bedroomAreaRanges": [
        {"name": "Room 1", "minArea": "23", "maxArea": "28", "unit": "m²"},
        {"name": "Room 2", "minArea": "18", "maxArea": "22", "unit": "m²"},
        {"name": "Room 3", "minArea": "18", "maxArea": "22", "unit": "m²"},
        {"name": "Room 4", "minArea": "18", "maxArea": "22", "unit": "m²"}
      ],
      "keyRooms": ["walk-in closet", "balcony"],
      "prompt": "Upper floor with a master bedroom and family living area",
      "modelType": "Pro"
    },
    "output": {
      "resultUrl": "https://cdn.ideal.house/output/floor-plan.jpg",
      "width": 2496,
      "height": 1664
    }
  }
}

Réponse de traitement#

json
{
  "code": 0,
  "message": "success",
  "data": {
    "id": 1234567890123456789,
    "status": "Processing",
    "waitNumber": 1,
    "percentage": 45,
    "input": {
      "bedrooms": 4,
      "bathrooms": 2,
      "totalArea": "200 m²",
      "modelType": "Pro"
    },
    "output": null
  }
}

Réponse de tâche échouée#

json
{
  "code": 0,
  "message": "success",
  "data": {
    "id": 1234567890123456789,
    "status": "Failed",
    "waitNumber": 0,
    "percentage": 0,
    "input": {
      "bedrooms": 4,
      "bathrooms": 2,
      "totalArea": "200 m²",
      "modelType": "Pro"
    },
    "output": null
  }
}

Champs de résultat#

ChampTypeDescription
idlongID de tâche
statusstringStatut actuel de la tâche
waitNumberintegerNombre de tâches devant dans la file d'attente ; 0 signifie aucune tâche en attente devant
percentageintegerPourcentage de complétion approximatif de 0 à 100
inputobjectEntrée de tâche normalisée, y compris les plages de chambres déduites automatiquement lorsque cela s'applique
outputobject / nullSortie générée lorsque la tâche réussit ; sinon généralement null
output.resultUrlstringURL signée de l'image de plan d'étage générée
output.widthintegerLargeur de sortie en pixels
output.heightintegerHauteur de sortie en pixels

📊 État de la tâche#

ÉtatDescription
UnprocessedLa tâche a été créée mais n'a pas commencé
ProcessingLa tâche est en cours de traitement
SuccessLa tâche est terminée et output.resultUrl est disponible
FailedLa tâche a échoué
TerminationLa tâche a été interrompue ou terminée

Interroger toutes les 3–5 secondes. Voir Limite de Tâche de l'API.


❌ Réponses d'erreur#

Toutes les réponses d'erreur utilisent la structure de réponse commune :

json
{
  "code": 1011,
  "message": "bedroomAreaRanges size must match bedrooms",
  "data": null
}
CodeNomDescriptionAction suggérée
1001FAILEDÉchec générique de la requêteVérifiez le champ message
1003INTERNAL_ERRORErreur interne du serveurRéessayez plus tard ; contactez le support si cela persiste
1011PARAM_ERRORParamètre de requête invalideVérifiez les nombres de pièces, unités, valeurs enum et tableaux imbriqués
5002API_KEY_INVALIDClé API invalide ou manquanteVérifiez l'en-tête APIKEY
9010SCAN_TEXT_ERRORL'invite a échoué au contrôle de contenuModifiez l'invite
9038PROHIBITED_CONTENTLa sortie générée contient du contenu interditAjustez les entrées et réessayez
9051COINS_NOT_ENOUGHCrédits insuffisantsAjoutez des crédits et réessayez

Voir Référence des Codes d'Erreur pour la liste complète des erreurs courantes.


🔄 Notes d'Intégration Web#

L'application Web authentifiée et l'API publique utilisent des points de terminaison et des méthodes d'authentification différentes :

ClientPoint de terminaisonAuthentification
Application WebPOST /floorPlan/generateEn-tête de connexion token
API publiquePOST /api/v1/floorPlan/generateEn-tête APIKEY

Les formes de champs commerciaux sont alignées, mais les clients de l'API publique doivent suivre les limites côté serveur et le contrat public dans ce document. En particulier :

  • Les clients Web peuvent inclure imageNumbers et extData internes ; les clients publics n'en ont pas besoin.
  • L'API publique détermine les métadonnées d'appel API à partir de le point de terminaison et des identifiants. Des champs de requête tels que isApiCall et genByMember sont inutiles.
  • balcon est accepté pour la compatibilité et normalisé en balcony ; les nouvelles intégrations doivent envoyer balcony.
  • Les limites serveurs publiques actuelles restent 0–5 chambres et 0.5–4 salles de bains même si une autre interface utilisateur présente temporairement des sélecteurs plus larges.