Ideal House
Pular para o conteúdo

Documentação da API de geração de plantas baixas#

URL Base: https://api.ideal.house
Versão: v1
Atualizado: 2026-08-09


📖 Visão Geral#

A API de geração de plantas baixas cria um projeto de planta baixa residencial em preto e branco, vista superior, estilo CAD, com base em requisitos estruturados de ambientes e em um prompt personalizado opcional ou imagem de referência.

O resultado destina-se à exploração inicial do layout. Não se trata de um desenho construtivo; dimensões, geometria, posicionamento de louças e conformidade com as normas de construção devem ser revisados por profissional qualificado.

O fluxo é assíncrono:

  1. Criar uma tarefa — Envie os parâmetros da planta baixa e receba um taskId.
  2. Consultar resultados — Consulte o endpoint de resultado com o taskId até que a tarefa alcance um status final.

🔐 Autenticação#

Todas as requisições públicas da API devem incluir uma chave API.

CabeçalhoObrigatórioValor
APIKEY✅ SimSua chave API
Content-Type✅ Sim para POSTapplication/json

[!WARNING] Mantenha sua chave API segura. Não a exponha em código do lado do cliente ou repositórios públicos.


💰 Dedução de Créditos#

Os créditos são deduzidos após a criação bem-sucedida de uma tarefa de geração. Se a tarefa falhar, os créditos deduzidos são estornados automaticamente. Créditos insuficientes retornam o código de erro 9051.

Modelo (modelType)Tamanho da saídaCréditos
Base1536 × 102410
Pro2496 × 166420

Flash não é suportado pela API de Planta Baixa API.

Consulte Referência de Dedução de Créditos para comportamento comum de cobrança.


📌 Endpoints da API#

1. Criar Tarefa de Planta Baixa#

Cria uma tarefa de geração de planta baixa e retorna um ID de tarefa único.

Endpointo

http
POST /api/v1/floorPlan/generate

Cabeçalhos da requisição

CabeçalhoObrigatórioDescrição
APIKEY✅ SimChave de autenticação da API
Content-Type✅ SimDeve ser application/json

Corpo da requisição#

CampoTipoObrigatórioDescriçãoPadrão
bedroomsinteger❌ NãoQuantidade de quartos de 0 a 52
bathroomsnumber❌ NãoQuantidade total de banheiros de 0.5 a 4, em incrementos de 0.51.5
totalAreastring✅ SimÁrea total alvo positiva com unidade ou ft², como 220 m² ou 1386 ft²
bedroomAreaRangesarray<object>❌ NãoOrientação opcional de dimensionamento de quartos. Veja Intervalos de Área dos QuartosDerivado de totalArea quando omitido
bathroomDetailsobject❌ NãoPreferências apenas para banheiros completos. Veja Detalhes do Banheiro
kitchenDetailsobject❌ NãoConfiguração opcional da cozinha. Veja Detalhes da Cozinha
keyRoomsarray<string>❌ NãoAmbientes ou espaços adicionais. Veja Ambientes Principais[]
promptstring❌ NãoPrioridades adicionais de layout. Não pode substituir contagens estruturadas ou restrições visuais rígidas""
refImageUrlstring❌ NãoURL da imagem de referência de acesso público""
modelTypestring❌ NãoEnum: Base, ProBase

[!IMPORTANT] A API pública API atualmente valida bedrooms como 0–5 e bathrooms como 0.5–4. Valores disponíveis em outra interface do cliente não ampliam esses limites no lado do servidor.

Regras gerais de requisição#

  • Todos os valores de enumeração diferenciam maiúsculas de minúsculas e devem usar os valores em inglês apresentados neste documento.
  • totalArea é uma área total alvo usada para orientar escala e proporções; não é tratada como uma dimensão construtiva exata.
  • O prompt personalizado efetivo é limitado aos primeiros 800 caracteres quando o prompt de imagem estruturado é montado.
  • Campos estruturados têm precedência sobre instruções conflitantes em prompt.
  • Uma tarefa bem-sucedida gera exatamente uma imagem.

📐 Área Total#

totalArea contém um valor numérico positivo seguido de uma unidade de área.

UnidadeExemplo
220 m²
ft²1386 ft²

Espaço em branco antes da unidade é recomendado. Valores decimais são aceitos quando positivos.

Exemplos válidos:

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

🛏️ Intervalos de Área dos Quartos#

bedroomAreaRanges fornece orientação relativa de dimensionamento de quartos. Não solicita rótulos de área numérica na imagem gerada.

Cada item tem o seguinte formato:

CampoTipoObrigatórioDescrição
namestring❌ NãoIdentidade do quarto, por exemplo Room 1 (Master) ou Room 2
minAreastring❌ NãoÁrea mínima positiva
maxAreastring❌ NãoÁrea máxima positiva; não pode ser menor que minArea
unitstring❌ NãoEnum: , ft²; use a mesma unidade que totalArea

Exemplo de intervalo explícito

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

Regras quando um array não vazio é fornecido:

  • Seu comprimento deve ser igual a bedrooms.
  • Cada minArea e maxArea fornecido deve ser uma string numérica positiva.
  • Quando ambos os valores são fornecidos, minArea <= maxArea.
  • unit, quando fornecido, deve ser ou ft².
  • Os nomes são preservados. Itens vazios ou nulos não fornecem orientação de dimensionamento.

Intervalos automáticos quando omitido#

O campo pode ser omitido ou enviado como array vazio. Quando nenhum item contém minArea ou maxArea eficaz, o caminho de geração estruturado deriva intervalos internos de quartos a partir de totalArea e bedrooms:

  • O orçamento de área do quarto começa em 20% da área total para um quarto.
  • O orçamento aumenta em 7.5 pontos percentuais para cada quarto adicional, limitado a 50%.
  • O primeiro quarto recebe um peso de dimensionamento de 1.3; cada outro quarto recebe um peso de 1.0.
  • Cada alvo se torna um intervalo aproximado de ±10%, arredondado para unidades de área inteiras.
  • A unidade é herdada de totalArea.
  • Nomes de quartos não vazios existentes são mantidos; caso contrário, o servidor usa Room 1, Room 2, e assim por diante.

Para 200 m² e 4 quartos, a orientação derivada atual é aproximadamente:

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²" }
]

Esses valores são orientação proporcional interna, não áreas finais garantidas dos ambientes. Intervalos válidos explícitos sempre têm precedência sobre intervalos automáticos.

Quando bedrooms é 0, omita bedroomAreaRanges ou envie [].


🛁 Detalhes do Banheiro#

bathrooms representa a contagem total de banheiros:

  • Sua parte inteira é o número de banheiros completos.
  • Uma fração .5 adiciona um lavabo.
  • Cada banheiro completo é configurado para incluir vaso sanitário, bancada com pia ou lavatório e chuveiro ou área molhada.
  • Um lavabo contém apenas vaso sanitário e bancada com pia ou lavatório, sem chuveiro ou banheira.

bathroomDetails configura apenas banheiros completos:

json
{
  "bathroomDetails": {
    "fullBathroomOptions": [
      {
        "name": "Bathroom 1",
        "wetDrySeparation": "yes",
        "bathtub": "required"
      },
      {
        "name": "Bathroom 2",
        "wetDrySeparation": "no",
        "bathtub": "optional"
      }
    ]
  }
}
CampoTipoValores permitidosDescrição
namestringBathroom 1, Bathroom 2, etc.Identidade de exibição opcional
wetDrySeparationstring / nullyes, no, nullSe deve exibir zona molhada separada
bathtubstring / nullno, optional, required, nullPreferência de banheira

Regras:

  • fullBathroomOptions.length não pode exceder floor(bathrooms).
  • O array só pode conter os banheiros completos para os quais preferências foram selecionadas.
  • Um valor null significa não especificado.
  • Uma banheira obrigatória é adicional às louças padrão do banheiro completo; não substitui o vaso sanitário ou chuveiro.
  • Separação molhada/seca é uma divisória interna dentro de um banheiro contabilizado, não um banheiro adicional.

🍳 Detalhes da Cozinha#

Todos os campos filhos de kitchenDetails são opcionais. Omita o objeto inteiro quando nenhuma preferência de cozinha for selecionada.

json
{
  "kitchenDetails": {
    "type": "open",
    "size": "standard",
    "layout": "U",
    "islandType": "preparation",
    "storage": "maximum",
    "features": ["breakfast nook", "pantry"]
  }
}
CampoTipoValores permitidos
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

Configuração parcial é válida. Por exemplo:

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

🚪 Ambientes Principais#

keyRooms aceita um array com esses valores exatos:

ValorDescrição
walk-in closetCloset dedicado conectado a uma zona de quartos
laundry roomEspaço de lavanderia dedicado
storage roomSala de armazenamento geral
utility roomSala mecânica ou de serviços
home officeHome office ou estudo dedicado
garageGaragem com abertura externa para veículo e acesso interno ao lar
pantryDespensa adjacente à cozinha
combined living-diningUm ambiente compartilhado de sala e jantar
balconyVaranda externa conectada à área social ou ao quarto principal

O valor legado da Web balcon também é aceito e normalizado para balcony.

Regras:

  • Valores em branco são ignorados e valores duplicados são removidos.
  • Ambientes principais selecionados são solicitados uma vez.
  • Espaços opcionais não selecionados são excluídos do programa de ambientes gerado.
  • Se pantry aparecer em ambos kitchenDetails.features e keyRooms, apenas uma despensa será solicitada.

Exemplo:

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

🖼️ Imagem de Referência#

refImageUrl é opcional e deve ser diretamente acessível pelo servidor da API.

Requisitos:

  • Formato: JPG/JPEG, PNG ou WebP.
  • Tamanho máximo do arquivo: 20 MB.
  • Dimensões mínimas: 128 × 128 px.
  • Dimensões máximas: 6,000 × 6,000 px. Imagens maiores são dimensionadas proporcionalmente antes do processamento.

A imagem de referência orienta layout, adjacência, proporções ou estilo visual. Ela não substitui contagens estruturadas de ambientes ou outras restrições rígidas.


🤖 Tipos de Modelo#

ValorDescrição
BasePadrão. Qualidade equilibrada de geração, saída 1536 × 1024
ProSaída de maior resolução 2496 × 1664 com tempo de geração esperado mais longo

Somente Base e Pro são suportados.


Campos não presentes no contrato público da API#

Os clientes da API pública não devem depender dos campos a seguir:

CampoNotas
imageNumbersO gerador atual sempre retorna uma imagem; este campo não é necessário
extDataMetadados internos de rastreamento de grupo de tarefas da Web; clientes públicos devem omiti-lo
isApiCallDeterminado pelo endpoint da API, não pelo corpo da requisição
genByMemberMetadado interno de geração, não um campo de requisição de Planta Baixa

Campos legados removidos que não devem ser enviados:

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

📥 Exemplos de Criação de Tarefa#

Requisição mínima com intervalos automáticos de quartos#

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"
  }'

Requisição completa#

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();

Resposta de sucesso na criação da tarefa#

json
{
  "code": 0,
  "message": "success",
  "data": 1234567890123456789
}
CampoTipoDescrição
codeinteger0 indica que a tarefa foi criada com sucesso
messagestringMensagem de resposta
datalongID da tarefa usado para consultar o endpoint de resultado

2. Obter Resultado da Tarefa#

Retorna o progresso da tarefa e a imagem gerada quando disponível.

Endpointo

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

Cabeçalhos da requisição

CabeçalhoObrigatórioDescrição
APIKEY✅ SimChave de autenticação da API

Parâmetros de query

ParâmetroTipoObrigatórioDescrição
taskIdlong✅ SimID da tarefa retornado pelo endpoint de criação

Exemplos de requisição de resultado#

cURL
bash
curl -X GET "https://api.ideal.house/api/v1/floorPlan/result?taskId=1234567890123456789" \
  -H "APIKEY: your_api_key_here"
Consulta periódica em Python
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"])
Consulta periódica em Node.js
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');

Resposta de tarefa concluída#

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
    }
  }
}

Resposta de processamento#

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
  }
}

Resposta de tarefa falhada#

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
  }
}

Campos do resultado#

CampoTipoDescrição
idlongID da tarefa
statusstringStatus atual da tarefa
waitNumberintegerNúmero de tarefas à frente na fila; 0 significa nenhuma tarefa na fila à frente
percentageintegerPorcentagem aproximada de conclusão de 0 a 100
inputobjectEntrada normalizada da tarefa, incluindo intervalos automáticos de quartos quando aplicável
outputobject / nullSaída gerada quando a tarefa é bem-sucedida; caso contrário geralmente null
output.resultUrlstringURL assinada da imagem da planta baixa gerada
output.widthintegerLargura de saída em pixels
output.heightintegerAltura de saída em pixels

📊 Status da Tarefa#

StatusDescrição
UnprocessedA tarefa foi criada mas ainda não iniciou
ProcessingA tarefa está sendo processada
SuccessTarefa concluída e output.resultUrl disponível
FailedA tarefa falhou
TerminationA tarefa foi interrompida ou terminada

Consulte a cada 3–5 segundos. Consulte Limite de Tarefas da API.


❌ Respostas de Erro#

Todas as respostas de erro usam a estrutura de resposta comum:

json
{
  "code": 1011,
  "message": "bedroomAreaRanges size must match bedrooms",
  "data": null
}
CódigoNomeDescriçãoAção sugerida
1001FAILEDFalha genérica na requisiçãoVerifique o campo message
1003INTERNAL_ERRORErro interno do servidorTente novamente mais tarde; entre em contato com o suporte se persistir
1011PARAM_ERRORParâmetro de requisição inválidoVerifique contagens, unidades, valores de enumeração e arrays aninhados
5002API_KEY_INVALIDChave API inválida ou ausenteVerifique o cabeçalho APIKEY
9010SCAN_TEXT_ERRORO prompt falhou na revisão de conteúdoRevise o prompt
9038PROHIBITED_CONTENTA saída gerada contém conteúdo proibidoAjuste os entradas e tente novamente
9051COINS_NOT_ENOUGHCréditos insuficientesAdicione créditos e tente novamente

Consulte Referência de Códigos de Erro para a lista completa de erros comuns.


🔄 Notas de Integração com a Web#

O aplicativo Web autenticado e a API pública API usam endpoints e métodos de autenticação diferentes:

ClienteEndpointAutenticação
Aplicativo WebPOST /floorPlan/generateCabeçalho de token token
API pública APIPOST /api/v1/floorPlan/generateCabeçalho APIKEY

Os formatos dos campos de negócio estão alinhados, mas clientes da API pública API devem seguir os limites no lado do servidor e o contrato público neste documento. Em particular:

  • Clientes Web podem incluir imageNumbers e extData internos; clientes públicos não precisam deles.
  • A API pública API determina metadados de chamada API com base no endpoint e nas credenciais. Campos de requisição como isApiCall e genByMember são desnecessários.
  • balcon é aceito por compatibilidade e normalizado para balcony; novas integrações devem enviar balcony.
  • Os limites atuais do servidor público permanecem 0–5 quartos e 0.5–4 banheiros, mesmo se outra interface apresentar seletores mais amplos temporariamente.