House Plan Generation API Documentation
Base URL:
https://api.ideal.house
Version: v1
Updated: 2026-06-12
📖 Overview
The House Plan Generation API allows you to create an AI-generated house plan presentation board based on architectural style, area, structural configuration, and interior layout preferences. Upon successful generation, the API produces exactly 1 composite result image per task. The image contains coordinated 2D floor plans, exterior elevations, and photorealistic exterior renderings in a single presentation board. The result is stored in output.resultUrl and also included as the only item in output.resultList. The workflow is asynchronous and involves two steps:
- Create a task — Submit your house plan parameters and receive a
taskId. - Poll for results — Use the
taskIdto query task status and retrieve the generated images.
🔐 Authentication
All API requests must be authenticated using an API Key.
Include your API Key in the request header:
| Header | Value |
|---|---|
APIKEY | your_api_key_here |
⚠️ Keep your API Key secure. Do not expose it in client-side code or public repositories.
💰 Credits Deduction
[!WARNING] 🪙 Credits are deducted based on the selected
modelTypeupon successful task creation. If the task ultimately fails, the deducted credits will be automatically refunded to your account.
Insufficient credits will return error code9051. 📄 See Credits Deduction Reference.
Model (modelType) | Credits Deducted |
|---|---|
Base | 10 credits |
Pro | 20 credits |
📌 API Endpoints
1. Create House Plan Task
Creates a new AI house plan generation task and returns a unique taskId for polling.
Endpoint
POST /api/v1/housePlan/generate
Request Headers
| Header | Required | Description |
|---|---|---|
APIKEY | ✅ Yes | Your API authentication key |
Content-Type | ✅ Yes | application/json |
Request Body
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
style | string / null | ✅ Yes | Architectural style English name. See Style Options | Barndominium |
stories | string | ✅ Yes | Number of stories. Enum: 1, 2, 3+ | 2 |
bedrooms | string | ✅ Yes | Number of bedrooms. Enum: 1, 2, 3, 4, 5+ | 2 |
bathrooms | string | ✅ Yes | Number of bathrooms. Enum: 1, 1.5, 2, 2.5, 3, 3.5, 4+ | 1 |
totalArea | string | ✅ Yes | Total area range in min-max unit format. See Total Area Options | 150-200 m² |
garageEnabled | boolean | ✅ Yes | Whether to include a garage | false |
garageType | string / null | ⚠️ Conditional | Required when garageEnabled=true. See Garage Type Options | null |
garageCapacity | string / null | ⚠️ Conditional | Required when garageEnabled=true. See Garage Capacity | null |
basement | string | ✅ Yes | Basement type. See Basement Options | None |
roofType | string / null | ❌ No | Roof structure type. See Roof Type Options | null |
outdoorSpaces | array<string> | ❌ No | Outdoor areas. See Outdoor Spaces Options | [] |
layoutConcept | string / null | ❌ No | Overall interior layout concept. See Layout Concept Options | null |
bedroomAreaRanges | array<object> | ✅ Yes | Bedroom area ranges. Length must match the bedroom count. See Bedroom Area Ranges | See example |
bathroomLayouts | array<object> | ✅ Yes | Bathroom layout selections. Length must be Math.floor(bathrooms). See Bathroom Layouts | See example |
kitchenLayout | string / null | ❌ No | Kitchen layout. See Kitchen Options | null |
kitchenFeatureOptions | array<string> | ❌ No | Optional kitchen features. See Kitchen Options | [] |
keyRooms | string / null | ❌ No | Special rooms joined by comma and space. See Key Rooms Options | null |
prompt | string | ❌ No | Custom text prompt to further guide generation | "" |
refImageUrl | string | ❌ No | URL of a reference house image to guide the style | "" |
modelType | string | ✅ Yes | Model quality type. Enum: Base, Pro. ⚠️ Flash mode is not supported | Base |
🎨 Style Options
| Value | Description |
|---|---|
Barndominium | Default. Metal barn-style hybrid home |
Cabin | Rustic wood cabin style |
Cape Cod | Classic New England symmetrical style |
Coastal | Light, airy beach-inspired style |
Colonial | Traditional symmetric colonial architecture |
Contemporary | Clean lines and modern materials |
Craftsman | Handcrafted details with natural materials |
Farmhouse | Rustic country farmhouse style |
French Country | Elegant French provincial style |
Mediterranean | Warm stucco with terracotta elements |
Mid-Century Modern | 1950s–70s clean geometric modernism |
Modern | Minimalist flat/angular modern design |
Ranch | Single-story sprawling layout |
Shingle Style | Continuous wood shingle exterior |
Southwestern | Adobe-inspired desert style |
Transitional | Blend of traditional and contemporary |
Tudor | Half-timbered medieval English style |
Victorian | Ornate 19th-century decorative style |
📐 Total Area Options
The totalArea field uses the format min-max unit. Metric values use m²; imperial values use ft². The minimum value must be lower than the maximum value by at least one step.
| Unit | Minimum | Maximum | Step | Example |
|---|---|---|---|---|
m² | 50 | 500 | 10 | 150-200 m² |
ft² | 500 | 5000 | 100 | 1500-2000 ft² |
🏠 Roof Type Options
| Value | Description |
|---|---|
Gable roof | Classic triangular peaked roof |
Hip roof | Slopes on all four sides |
Flat roof | Minimal pitch flat roof |
Pitched roof | General steeply sloped roof |
🏗️ Basement Options
| Value | Description |
|---|---|
None | No basement |
Partial | Partial basement |
Full | Full basement |
🚗 Garage Type Options
garageType is required only when garageEnabled=true; otherwise send null.
| Value | Description |
|---|---|
Detached | Detached garage |
Front Entry | Garage entry faces the front |
Side Entry | Garage entry faces the side |
Rear Entry | Garage entry faces the rear |
🚗 Garage Capacity
garageCapacity is required only when garageEnabled=true; otherwise send null.
| Value | Description |
|---|---|
1 | Single-car garage |
2 | Double-car garage |
3+ | Three or more car spaces |
🌿 Outdoor Spaces Options
The outdoorSpaces field accepts an array of the following values.
| Value | Description |
|---|---|
Front porch | Covered entrance porch at the front |
Covered patio | Covered outdoor patio area |
Deck | Wooden or composite deck |
Balcony | Elevated outdoor platform |
Courtyard | Enclosed or semi-enclosed outdoor yard |
Breezeway | Covered passageway connecting structures |
Outdoor Kitchen | Outdoor cooking and dining area |
Example
"outdoorSpaces": ["Front porch", "Deck", "Balcony"]
🏛️ Layout Concept Options
| Value | Description |
|---|---|
Open Concept | Open-plan connected living spaces |
Traditional | Separated rooms with defined boundaries |
Split-Level | Staggered floor levels between areas |
🛏️ Bedroom Area Ranges
The bedroomAreaRanges field must be an array whose length matches the bedrooms count. Each item uses the following shape:
| Field | Type | Description |
|---|---|---|
name | string | Bedroom display name, for example Room 1 (Master) |
minArea | string | Minimum bedroom area. Must be a non-negative numeric string |
maxArea | string | Maximum bedroom area. Must be greater than or equal to minArea |
unit | string | Area unit. Enum: m², ft² |
Default example for bedrooms="2"
[
{ "name": "Room 1 (Master)", "minArea": "12", "maxArea": "18", "unit": "m²" },
{ "name": "Room 2", "minArea": "10", "maxArea": "14", "unit": "m²" }
]
🛁 Bathroom Layouts
The bathroomLayouts field must be an array whose length is Math.floor(bathrooms). For example, bathrooms="2.5" requires 2 bathroom layout objects.
| Field | Type | Description |
|---|---|---|
name | string | Bathroom display name, for example Bathroom 1 |
layout | string / null | Enum: With Wet & Dry Separation, Without Separation, or null |
Default example for bathrooms="1"
[
{ "name": "Bathroom 1", "layout": null }
]
🍳 Kitchen Options
Kitchen Layout
| Value | Description |
|---|---|
Open Kitchen | Open kitchen connected to living/dining area |
Closed Kitchen | Enclosed separate kitchen space |
Kitchen Feature Options
| Value | Description |
|---|---|
Eating Bar | Eating bar / counter seating |
Kitchen Island | Kitchen island |
Breakfast Nook | Breakfast nook |
🚪 Key Rooms Options
The keyRooms field accepts one or more of the following values. When selecting multiple options, join them with a comma (,).
| Value | Description |
|---|---|
Home Office | Dedicated home office or study |
Bonus Room | Flexible multi-purpose bonus room |
Media Room | Home theater or media center |
Mudroom | Entry room for outdoor gear |
Laundry Room | Dedicated laundry space |
Guest Suite | Self-contained guest bedroom suite |
Example
"keyRooms": "Home Office, Media Room, Guest Suite"
Model Types
| Value | Description |
|---|---|
Base | Default. Balanced speed and quality. Generates a high-resolution composite presentation board |
Pro | Higher quality and higher-resolution output, slower |
⚠️ Note:
Flashmode is not available for this API. OnlyBaseandProare supported.
📥 Request Examples
cURL
# Basic request with default values
curl -X POST "https://api.ideal.house/api/v1/housePlan/generate" \
-H "APIKEY: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"style": "Barndominium",
"stories": "2",
"bedrooms": "2",
"bathrooms": "1",
"totalArea": "150-200 m²",
"garageEnabled": false,
"garageType": null,
"garageCapacity": null,
"basement": "None",
"roofType": null,
"outdoorSpaces": [],
"layoutConcept": null,
"bedroomAreaRanges": [
{ "name": "Room 1 (Master)", "minArea": "12", "maxArea": "18", "unit": "m²" },
{ "name": "Room 2", "minArea": "10", "maxArea": "14", "unit": "m²" }
],
"bathroomLayouts": [
{ "name": "Bathroom 1", "layout": null }
],
"kitchenLayout": null,
"kitchenFeatureOptions": [],
"keyRooms": null,
"prompt": "",
"refImageUrl": "",
"modelType": "Base"
}'
# Pro model with reference image and custom prompt
curl -X POST "https://api.ideal.house/api/v1/housePlan/generate" \
-H "APIKEY: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"style": "Victorian",
"stories": "3+",
"bedrooms": "5+",
"bathrooms": "4+",
"totalArea": "300-380 m²",
"garageEnabled": true,
"garageType": "Front Entry",
"garageCapacity": "3+",
"basement": "Full",
"roofType": "Gable roof",
"outdoorSpaces": ["Front porch", "Balcony", "Courtyard", "Outdoor Kitchen"],
"layoutConcept": "Traditional",
"bedroomAreaRanges": [
{ "name": "Room 1 (Master)", "minArea": "18", "maxArea": "28", "unit": "m²" },
{ "name": "Room 2", "minArea": "12", "maxArea": "16", "unit": "m²" },
{ "name": "Room 3", "minArea": "12", "maxArea": "16", "unit": "m²" },
{ "name": "Room 4", "minArea": "10", "maxArea": "14", "unit": "m²" },
{ "name": "Room 5", "minArea": "10", "maxArea": "14", "unit": "m²" }
],
"bathroomLayouts": [
{ "name": "Bathroom 1", "layout": "With Wet & Dry Separation" },
{ "name": "Bathroom 2", "layout": "With Wet & Dry Separation" },
{ "name": "Bathroom 3", "layout": "Without Separation" },
{ "name": "Bathroom 4", "layout": null }
],
"kitchenLayout": "Closed Kitchen",
"kitchenFeatureOptions": ["Kitchen Island", "Breakfast Nook"],
"keyRooms": "Home Office, Bonus Room, Media Room, Guest Suite",
"prompt": "Grand Victorian mansion with ornate details and wraparound porch",
"refImageUrl": "https://example.com/reference-house.jpg",
"modelType": "Pro"
}'
Java (OkHttp)
import okhttp3.*;
import java.io.IOException;
public class HousePlanApiExample {
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 IOException {
OkHttpClient client = new OkHttpClient();
String requestBody = """
{
"style": "Barndominium",
"stories": "2",
"bedrooms": "2",
"bathrooms": "1",
"totalArea": "150-200 m²",
"garageEnabled": false,
"garageType": null,
"garageCapacity": null,
"basement": "None",
"roofType": null,
"outdoorSpaces": [],
"layoutConcept": null,
"bedroomAreaRanges": [
{ "name": "Room 1 (Master)", "minArea": "12", "maxArea": "18", "unit": "m²" },
{ "name": "Room 2", "minArea": "10", "maxArea": "14", "unit": "m²" }
],
"bathroomLayouts": [
{ "name": "Bathroom 1", "layout": null }
],
"kitchenLayout": null,
"kitchenFeatureOptions": [],
"keyRooms": null,
"prompt": "",
"refImageUrl": "",
"modelType": "Base"
}
""";
Request request = new Request.Builder()
.url(BASE_URL + "/api/v1/housePlan/generate")
.addHeader("APIKEY", API_KEY)
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(requestBody, MediaType.parse("application/json")))
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
}
Python (requests)
import requests
BASE_URL = "https://api.ideal.house"
API_KEY = "your_api_key_here"
headers = {
"APIKEY": API_KEY,
"Content-Type": "application/json"
}
payload = {
"style": "Barndominium",
"stories": "2",
"bedrooms": "2",
"bathrooms": "1",
"totalArea": "150-200 m²",
"garageEnabled": False,
"garageType": None,
"garageCapacity": None,
"basement": "None",
"roofType": None,
"outdoorSpaces": [],
"layoutConcept": None,
"bedroomAreaRanges": [
{ "name": "Room 1 (Master)", "minArea": "12", "maxArea": "18", "unit": "m²" },
{ "name": "Room 2", "minArea": "10", "maxArea": "14", "unit": "m²" }
],
"bathroomLayouts": [
{ "name": "Bathroom 1", "layout": None }
],
"kitchenLayout": None,
"kitchenFeatureOptions": [],
"keyRooms": None,
"prompt": "",
"refImageUrl": "",
"modelType": "Base"
}
response = requests.post(
f"{BASE_URL}/api/v1/housePlan/generate",
headers=headers,
json=payload
)
data = response.json()
task_id = data.get("data")
print(f"Task ID: {task_id}")
Node.js (axios)
const axios = require('axios');
const BASE_URL = 'https://api.ideal.house';
const API_KEY = 'your_api_key_here';
async function createHousePlanTask() {
try {
const response = await axios.post(
`${BASE_URL}/api/v1/housePlan/generate`,
{
style: 'Barndominium',
stories: '2',
bedrooms: '2',
bathrooms: '1',
totalArea: '150-200 m²',
garageEnabled: false,
garageType: null,
garageCapacity: null,
basement: 'None',
roofType: null,
outdoorSpaces: [],
layoutConcept: null,
bedroomAreaRanges: [
{ name: 'Room 1 (Master)', minArea: '12', maxArea: '18', unit: 'm²' },
{ name: 'Room 2', minArea: '10', maxArea: '14', unit: 'm²' }
],
bathroomLayouts: [
{ name: 'Bathroom 1', layout: null }
],
kitchenLayout: null,
kitchenFeatureOptions: [],
keyRooms: null,
prompt: '',
refImageUrl: '',
modelType: 'Base'
},
{
headers: {
'APIKEY': API_KEY,
'Content-Type': 'application/json'
}
}
);
const taskId = response.data.data;
console.log('Task ID:', taskId);
return taskId;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}
createHousePlanTask();
📤 Response
Success Response
{
"code": 0,
"message": "success",
"data": 1234567890123456789
}
| Field | Type | Description |
|---|---|---|
code | integer | 0 indicates success |
message | string | Response message |
data | long | The unique task ID for polling results |
2. Get Task Result
Retrieves the current status and output of a previously created house plan task.
Endpoint
GET /api/v1/housePlan/result
Request Headers
| Header | Required | Description |
|---|---|---|
APIKEY | ✅ Yes | Your API authentication key |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
taskId | long | ✅ Yes | The task ID returned from the create task endpoint |
📥 Request Examples
cURL
curl -X GET "https://api.ideal.house/api/v1/housePlan/result?taskId=1234567890123456789" \
-H "APIKEY: your_api_key_here"
Java (OkHttp)
import okhttp3.*;
import java.io.IOException;
public class HousePlanResultExample {
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 IOException {
OkHttpClient client = new OkHttpClient();
long taskId = 1234567890123456789L;
Request request = new Request.Builder()
.url(BASE_URL + "/api/v1/housePlan/result?taskId=" + taskId)
.addHeader("APIKEY", API_KEY)
.get()
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
}
Python (requests)
import requests
import time
BASE_URL = "https://api.ideal.house"
API_KEY = "your_api_key_here"
headers = {
"APIKEY": API_KEY
}
task_id = 1234567890123456789
# Poll until task is complete
while True:
response = requests.get(
f"{BASE_URL}/api/v1/housePlan/result",
headers=headers,
params={"taskId": task_id}
)
data = response.json()
result = data.get("data", {})
status = result.get("status")
print(f"Status: {status}, Progress: {result.get('percentage')}%, Queue: {result.get('waitNumber')}")
if status in ("Success", "Failed", "Termination"):
break
time.sleep(3) # Poll every 3 seconds
if status == "Success":
output = result["output"]
print("Composite Result URL:", output["resultUrl"])
print("Result List:", output.get("resultList", []))
else:
print("Task ended with status:", status)
Node.js (axios)
const axios = require('axios');
const BASE_URL = 'https://api.ideal.house';
const API_KEY = 'your_api_key_here';
async function pollResult(taskId) {
const headers = { 'APIKEY': API_KEY };
while (true) {
const response = await axios.get(
`${BASE_URL}/api/v1/housePlan/result`,
{
headers,
params: { taskId }
}
);
const result = response.data.data;
const { status, percentage, waitNumber } = result;
console.log(`Status: ${status} | Progress: ${percentage}% | Queue: ${waitNumber}`);
if (['Success', 'Failed', 'Termination'].includes(status)) {
if (status === 'Success') {
console.log('Composite Result URL:', result.output.resultUrl);
console.log('Result List:', result.output.resultList);
} else {
console.log('Task ended with status:', status);
}
break;
}
// Wait 3 seconds before next poll
await new Promise(resolve => setTimeout(resolve, 3000));
}
}
pollResult(1234567890123456789n);
📤 Response
📸 Note: This API generates exactly 1 composite result image per successful task. The image combines 2D floor plans, exterior elevations, and photorealistic exterior renderings in a single presentation board. The
output.resultUrlcontains the composite image URL, andoutput.resultListcontains the same URL as a single-item array for compatibility.
Success Response (Task Completed)
{
"code": 0,
"message": "success",
"data": {
"id": 1234567890123456789,
"status": "Success",
"waitNumber": 0,
"percentage": 100,
"input": {
"style": "Barndominium",
"stories": "2",
"bedrooms": "2",
"bathrooms": "1",
"totalArea": "150-200 m²",
"garageEnabled": false,
"garageType": null,
"garageCapacity": null,
"basement": "None",
"roofType": null,
"outdoorSpaces": [],
"layoutConcept": null,
"bedroomAreaRanges": [
{ "name": "Room 1 (Master)", "minArea": "12", "maxArea": "18", "unit": "m²" },
{ "name": "Room 2", "minArea": "10", "maxArea": "14", "unit": "m²" }
],
"bathroomLayouts": [
{ "name": "Bathroom 1", "layout": null }
],
"kitchenLayout": null,
"kitchenFeatureOptions": [],
"keyRooms": null,
"prompt": "",
"refImageUrl": "",
"modelType": "Base"
},
"output": {
"resultUrl": "https://cdn.ideal.house/output/house_plan_composite.jpg",
"resultList": [
"https://cdn.ideal.house/output/house_plan_composite.jpg"
],
"width": 2560,
"height": 1440
}
}
}
Response (Task Processing / In Queue)
{
"code": 0,
"message": "success",
"data": {
"id": 1234567890123456789,
"status": "Processing",
"waitNumber": 1,
"percentage": 45,
"input": {
"style": "Barndominium",
"stories": "2",
"bedrooms": "2",
"bathrooms": "1",
"totalArea": "150-200 m²",
"garageEnabled": false,
"garageType": null,
"garageCapacity": null,
"basement": "None",
"roofType": null,
"outdoorSpaces": [],
"layoutConcept": null,
"bedroomAreaRanges": [
{ "name": "Room 1 (Master)", "minArea": "12", "maxArea": "18", "unit": "m²" },
{ "name": "Room 2", "minArea": "10", "maxArea": "14", "unit": "m²" }
],
"bathroomLayouts": [
{ "name": "Bathroom 1", "layout": null }
],
"kitchenLayout": null,
"kitchenFeatureOptions": [],
"keyRooms": null,
"prompt": "",
"refImageUrl": "",
"modelType": "Base"
},
"output": null
}
}
Response (Task Failed)
{
"code": 0,
"message": "success",
"data": {
"id": 1234567890123456789,
"status": "Failed",
"waitNumber": 0,
"percentage": 0,
"input": {
"style": "Barndominium",
"stories": "2",
"bedrooms": "2",
"bathrooms": "1",
"totalArea": "150-200 m²",
"garageEnabled": false,
"basement": "None",
"modelType": "Base"
},
"output": null
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
id | long | Task unique identifier |
status | string | Current task status (see Task Status) |
waitNumber | integer | Number of tasks ahead in the queue (0 means currently processing) |
percentage | integer | Task completion percentage (0–100) |
input | object | The original input parameters of the task |
input.style | string | Architectural style |
input.totalArea | string | Total area range |
input.stories | string | Number of floors |
input.bedrooms | string | Number of bedrooms |
input.bathrooms | string | Number of bathrooms |
input.garageEnabled | boolean | Whether a garage was requested |
input.garageType | string / null | Garage type |
input.garageCapacity | string / null | Number of garage spaces |
input.basement | string | Basement type |
input.roofType | string | Roof type |
input.outdoorSpaces | array<string> | Outdoor spaces |
input.layoutConcept | string | Overall layout concept |
input.bedroomAreaRanges | array<object> | Bedroom area ranges |
input.bathroomLayouts | array<object> | Bathroom layout selections |
input.kitchenLayout | string | Kitchen layout style |
input.kitchenFeatureOptions | array<string> | Optional kitchen features |
input.keyRooms | string | Key special rooms (comma-separated) |
input.prompt | string | Custom text prompt (if provided) |
input.refImageUrl | string | Reference image URL (if provided) |
input.modelType | string | Model type used |
output | object | Generation result (only available when status is Success) |
output.resultUrl | string | URL to the generated composite house plan presentation board |
output.resultList | array<string> | URLs to generated result images. For House Plan, this is normally a single-item array containing the same URL as output.resultUrl |
output.width | integer | Output width in pixels |
output.height | integer | Output height in pixels |
📊 Task Status
| Status | Description |
|---|---|
Unprocessed | Task has been created but not yet started |
Processing | Task is currently being processed |
Success | Task completed successfully — output is available |
Failed | Task failed due to an error |
Termination | Task was interrupted or terminated |
Poll every 3-5 seconds. See API Task Limit.
❌ Error Responses
All error responses share the same JSON structure:
{
"code": 5002,
"message": "Invalid API Key",
"data": null
}
Error Code Reference
| Code | Name | Description | Suggested Action |
|---|---|---|---|
1001 | FAILED | Request failed (generic error) | Check the message field for specific error details |
1003 | INTERNAL_ERROR | Internal server error | Retry after a short delay; contact support if it persists |
1011 | PARAM_ERROR | Request parameter error | Verify all required parameters are provided and correctly formatted |
5002 | API_KEY_INVALID | Invalid or missing API Key | Ensure the APIKEY header is present and the value is correct |
9010 | SCAN_TEXT_ERROR | Text prompt failed content review | Modify the prompt to remove any sensitive or prohibited content |
9038 | PROHIBITED_CONTENT | Generated output image contains prohibited content | Adjust prompt/style/inputs and retry |
9051 | COINS_NOT_ENOUGH | Insufficient coins / credits | Top up your account credits and retry |
📄 For the complete list of common API error codes, refer to the Error Code Reference.