Skip to main content

API Reference

Base URL: https://api-lux.upskiller.xyz/v2

All endpoints except health check require authentication. Include Authorization: Bearer YOUR_API_TOKEN in request headers.

Complete API documentation with request/response schemas: Swagger UI

Endpoints

EndpointMethodDescription
/GETServer health check
/runPOSTEnd-to-end daylight simulation
/obstruction_allPOSTCalculate obstruction angles in 64 directions
/horizonPOSTCalculate single horizon angle
/zenithPOSTCalculate single zenith angle
/obstructionPOSTCalculate both horizon and zenith for one direction
/get-reference-pointPOSTGet window center point
/calculate-directionPOSTGet window normal direction
/encodePOSTEncode room parameters to model input
/encode_rawPOSTEncode with pre-calculated angles
/statsPOSTCalculate daylight statistics
/mergePOSTMerge multiple window results

GET /

Check server status.

Request

GET https://api-lux.upskiller.xyz/v2/

No authentication required.

Response

{
"status": "running",
"services": {
"encoder": "ready",
"merger": "ready",
"model": "ready",
"obstruction": "ready",
"stats": "ready"
}
}

Example

curl https://api-lux.upskiller.xyz/v2/

POST /run

Executes complete daylight simulation: obstruction calculation, encoding, and model prediction.

Request Body

PropertyTypeDescription
model_typestringdf_default, da_default, df_custom, or da_custom
parametersobjectRoom and window geometry
mesharrayTriangle mesh. Each 3 consecutive [x, y, z] points form a triangle
horizonarray(Optional) Pre-calculated horizon angles (64 floats). Can be at top level or per-window
zenitharray(Optional) Pre-calculated zenith angles (64 floats). Can be at top level or per-window

When both horizon and zenith are provided, obstruction calculation is skipped, improving performance by 30-50%.

Parameters Object

Required properties
PropertyTypeRangeUnitDescription
height_roof_over_floorfloat0-30mFloor to ceiling distance
floor_height_above_terrainfloat0-10mFloor elevation above ground
room_polygonarray-mRoom outline as [[x, y], ...] coordinate pairs
windowsobject--Window definitions keyed by ID
Optional properties
PropertyTypeRangeDescription
ceiling_reflectancefloat0.50-0.90Light reflectance of ceiling (default 0.80)
horizontal_reflectancefloat0.05-0.60Light reflectance of floor (default 0.30)
vertical_reflectancefloat0.30-0.90Light reflectance of walls (default 0.70)
facade_reflectancefloat0.10-0.60Light reflectance of facade (default 0.30)
terrain_reflectancefloat0.05-0.40Light reflectance of ground (default 0.20)

Window Object

Required properties per window
PropertyTypeRangeUnitDescription
x1, y1, z1float-mFirst corner of window bounding box
x2, y2, z2float-mOpposite corner of window bounding box
window_frame_ratiofloat0-1-Fraction of window occupied by frame
Optional properties per window
PropertyTypeDescription
horizonarrayPre-calculated horizon angles (64 floats) for this window
zenitharrayPre-calculated zenith angles (64 floats) for this window

When specified per-window, these override top-level values for that specific window.

Request Example (Basic)

{
"model_type": "df_default",
"parameters": {
"height_roof_over_floor": 2.7,
"floor_height_above_terrain": 0.5,
"room_polygon": [
[0, 0],
[0, 5],
[-4, 5],
[-4, 0]
],
"windows": {
"main_window": {
"x1": -0.5,
"y1": 5,
"z1": 0.9,
"x2": -2,
"y2": 5.2,
"z2": 2.4,
"window_frame_ratio": 0.2
}
}
},
"mesh": [
[10, 0, 0],
[10, 0, 8],
[10, 20, 8],
[10, 20, 8],
[10, 20, 0],
[10, 0, 0]
]
}
Request Example with Pre-calculated Obstruction Angles

Skip obstruction calculation by providing horizon and zenith arrays at the top level:

{
"model_type": "df_default",
"parameters": {
"height_roof_over_floor": 2.7,
"floor_height_above_terrain": 0.5,
"room_polygon": [
[0, 0],
[0, 5],
[-4, 5],
[-4, 0]
],
"windows": {
"main_window": {
"x1": -0.5,
"y1": 5,
"z1": 0.9,
"x2": -2,
"y2": 5.2,
"z2": 2.4,
"window_frame_ratio": 0.2
}
}
},
"mesh": [
[10, 0, 0],
[10, 0, 8],
[10, 20, 8],
[10, 20, 8],
[10, 20, 0],
[10, 0, 0]
],
"horizon": [15.5, 16.2, 14.8 /* ... 64 values total */],
"zenith": [10.2, 11.1, 9.8 /* ... 64 values total */]
}

Or specify per-window for multi-window scenarios:

{
"model_type": "df_default",
"parameters": {
"height_roof_over_floor": 2.7,
"floor_height_above_terrain": 0.5,
"room_polygon": [
[0, 0],
[0, 5],
[-4, 5],
[-4, 0]
],
"windows": {
"window_1": {
"x1": -0.5,
"y1": 5,
"z1": 0.9,
"x2": -2,
"y2": 5.2,
"z2": 2.4,
"window_frame_ratio": 0.2,
"horizon": [30, 30 /* ... 64 values */],
"zenith": [30, 30 /* ... 64 values */]
},
"window_2": {
"x1": 0,
"y1": 1,
"z1": 0.9,
"x2": 0.4,
"y2": 4,
"z2": 2.4,
"window_frame_ratio": 0.2,
"horizon": [0, 0 /* ... 64 values */],
"zenith": [0, 0 /* ... 64 values */]
}
}
},
"mesh": [
[10, 0, 0],
[10, 0, 8],
[10, 20, 8]
]
}

Response

{
"status": "success",
"result": [[/* df values array */]],
"mask": [[/*bool mask showing the room boundary*/]]
}

Sample response JSON

Example

curl -X POST https://api-lux.upskiller.xyz/v2/run \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model_type": "df_default",
"parameters": {
"height_roof_over_floor": 2.7,
"floor_height_above_terrain": 0.5,
"room_polygon": [[0, 0], [0, 5], [-4, 5], [-4, 0]],
"windows": {
"main_window": {
"x1": -0.5, "y1": 5, "z1": 0.9,
"x2": -2, "y2": 5.2, "z2": 2.4,
"window_frame_ratio": 0.2
}
}
},
"mesh": [
[10, 0, 0], [10, 0, 8], [10, 20, 8],
[10, 20, 8], [10, 20, 0], [10, 0, 0]
]
}'

POST /obstruction_all

Calculates horizon and zenith angles in 64 directions around a window.

Request Body

PropertyTypeDescription
room_polygonarrayRoom outline as [[x, y], ...] coordinate pairs
windowsobjectWindow definitions (same format as /run)
mesharrayTriangle mesh as [x, y, z] points

The endpoint calculates reference points and direction angles automatically from window geometry.

Response

{
"status": "success",
"horizon": [/* 64 angles in degrees */],
"zenith": [/* 64 angles in degrees */]
}

Example

curl -X POST https://api-lux.upskiller.xyz/v2/obstruction_all \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"room_polygon": [[0, 0], [0, 7], [-3, 7], [-3, 0]],
"windows": {
"window_1": {
"x1": -1.0,
"y1": 7,
"z1": 2.8,
"x2": -2,
"y2": 7.3,
"z2": 5.4,
"window_frame_ratio": 0.41
}
},
"mesh": [
[10, 0, 0], [10, 0, 8], [10, 20, 8],
[10, 20, 8], [10, 20, 0], [10, 0, 0]
]
}'

POST /horizon

Calculates single horizon obstruction angle for a specific direction.

Request Body

PropertyTypeDescription
xfloatWindow center X coordinate
yfloatWindow center Y coordinate
zfloatWindow center Z coordinate
direction_anglefloatDirection angle in degrees (0-360)
mesharrayTriangle mesh

Response

{
"status": "success",
"horizon": 15.5
}

Example

curl -X POST https://api-lux.upskiller.xyz/v2/horizon \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"x": 0.0,
"y": 3.0,
"z": 1.5,
"direction_angle": 90.0,
"mesh": [[10, 0, 0], [10, 0, 8], [10, 20, 8]]
}'

POST /zenith

Calculates single zenith obstruction angle for a specific direction.

Request and response format identical to /horizon.

Response

{
"status": "success",
"zenith": 10.2
}

POST /obstruction

Calculates both horizon and zenith angles in a single request for a specific direction.

Request Body

PropertyTypeDescription
xfloatWindow center X coordinate
yfloatWindow center Y coordinate
zfloatWindow center Z coordinate
direction_anglefloatDirection angle in degrees (0-360)
mesharrayTriangle mesh

Response

{
"status": "success",
"data": {
"horizon": {
"obstruction_angle_degrees": 26.57,
"obstruction_angle_radians": 0.4636,
"highest_point": { "x": 10.0, "y": 0.0, "z": 8.0 },
"projected_point_count": 6
},
"zenith": {
"obstruction_angle_degrees": 56.31,
"obstruction_angle_radians": 0.9828,
"highest_point": { "x": 8.0, "y": 0.0, "z": 5.0 },
"projected_point_count": 6
}
}
}

Sample response JSON

Example

import requests

url = "https://api-lux.upskiller.xyz/v2/obstruction"
headers = {"Authorization": "Bearer YOUR_API_TOKEN"}
payload = {
"x": 0.0,
"y": 3.0,
"z": 1.5,
"direction_angle": 90.0,
"mesh": [
[10, 0, 0], [10, 0, 8], [10, 20, 8],
[10, 20, 8], [10, 20, 0], [10, 0, 0]
]
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()
print(f"Horizon: {result['data']['horizon']['obstruction_angle_degrees']:.2f}°")
print(f"Zenith: {result['data']['zenith']['obstruction_angle_degrees']:.2f}°")

POST /get-reference-point

Returns the center point (reference point) of each window for obstruction calculations.

Request Body

PropertyTypeDescription
room_polygonarrayRoom outline as [[x, y], ...]
windowsobjectWindow definitions

Response

{
"status": "success",
"windows": {
"test_window": {
"reference_point": { "x": -1.2, "y": 7.1, "z": 4.1 }
}
}
}

Example

import requests

url = "https://api-lux.upskiller.xyz/v2/get-reference-point"
headers = {"Authorization": "Bearer YOUR_API_TOKEN"}
payload = {
"room_polygon": [[0, 0], [0, 7], [-3, 7], [-3, 0]],
"windows": {
"test_window": {
"x1": -2, "y1": 7, "z1": 2.8,
"x2": -0.4, "y2": 7.2, "z2": 5.4
}
}
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()
print(result['windows']['test_window']['reference_point'])

POST /calculate-direction

Calculates the outward normal direction angle for each window.

Request Body

Same format as /get-reference-point.

Response

{
"status": "success",
"windows": {
"test_window": {
"direction_angle": 90.5
}
}
}

POST /encode

Encodes room and window parameters into model input format (ZIP file with NPY arrays).

Request Body

PropertyTypeDescription
model_typestringModel type (df_default, etc.)
parametersobjectRoom and window geometry
mesharrayTriangle mesh

Response

Binary ZIP file containing image.npy (128×128 encoded array).

Example

import requests
import zipfile
from io import BytesIO
import numpy as np

url = "https://api-lux.upskiller.xyz/v2/encode"
headers = {"Authorization": "Bearer YOUR_API_TOKEN"}
payload = {
"model_type": "df_default",
"parameters": {
"height_roof_over_floor": 2.7,
"floor_height_above_terrain": 0.5,
"room_polygon": [[0, 0], [0, 5], [-4, 5], [-4, 0]],
"windows": {
"main_window": {
"x1": -0.5, "y1": 5, "z1": 0.9,
"x2": -2, "y2": 5.2, "z2": 2.4,
"window_frame_ratio": 0.2
}
}
},
"mesh": [[10, 0, 0], [10, 0, 8], [10, 20, 8]]
}

response = requests.post(url, headers=headers, json=payload)
zip_buffer = BytesIO(response.content)

with zipfile.ZipFile(zip_buffer, 'r') as zip_file:
with zip_file.open('image.npy') as npy_file:
image_array = np.load(npy_file)
print(f"Encoded shape: {image_array.shape}")

POST /encode_raw

Encodes room parameters using pre-calculated obstruction angles.

Request Body

Same as /encode, but window objects must include:

{
"direction_angle": 90.0,
"horizon": [/* 64 angles */],
"zenith": [/* 64 angles */]
}

Response format identical to /encode.


POST /stats

Calculates statistical metrics for daylight simulation results.

Request Body

PropertyTypeDescription
df_matrixarray2D array of daylight factor values
room_maskarray2D boolean array marking room area

Response

{
"status": "success",
"mean": 2.5,
"median": 2.3,
"min": 0.1,
"max": 5.8,
"std": 1.2
}

Sample response JSON

Example

import requests

url = "https://api-lux.upskiller.xyz/v2/stats"
headers = {"Authorization": "Bearer YOUR_API_TOKEN"}
payload = {
"df_matrix": [[1.2, 1.5, 1.8], [2.0, 2.3, 2.5]],
"room_mask": [[True, True, True], [True, True, True]]
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()
print(f"Mean DF: {result['mean']}%")
print(f"Median DF: {result['median']}%")

POST /merge

Merges multiple window simulation results into a single combined image.

Request Body

PropertyTypeDescription
window_resultsobjectWindow results keyed by window ID

Each window result contains df_matrix and room_mask arrays.

Response

{
"status": "success",
"merged_result": {
"df_matrix": [/* merged 2D array */],
"room_mask": [/* merged 2D array */]
}
}

Example

import requests

url = "https://api-lux.upskiller.xyz/v2/merge"
headers = {"Authorization": "Bearer YOUR_API_TOKEN"}
payload = {
"window_results": {
"window_1": {
"df_matrix": [[1.2, 1.5], [2.0, 2.3]],
"room_mask": [[True, True], [True, True]]
},
"window_2": {
"df_matrix": [[0.8, 1.0], [1.5, 1.8]],
"room_mask": [[True, True], [True, True]]
}
}
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()
print(f"Merged matrix shape: {len(result['merged_result']['df_matrix'])}")

Error Responses

All endpoints return errors in JSON format:

{
"status": "error",
"error": "Description of what went wrong",
"error_type": "validation_error"
}

HTTP Status Codes

CodeDescription
200Success
400Invalid parameters
401Invalid or missing API token
403Forbidden
500Internal server error
503Service unavailable
504Request timeout

Common Errors

Missing required field:

{
"error": "Missing required parameters: window_frame_ratio"
}

Out of range value:

{
"error": "Parameter 'height_roof_over_floor' value 35.0 outside valid range [0, 30]"
}

Invalid mesh:

{
"error": "Mesh must contain at least 3 points"
}