Documentation Index
Fetch the complete documentation index at: https://docs.solargenix.ai/llms.txt
Use this file to discover all available pages before exploring further.
This document describes the roof layout API used to generate a roof layout based on latitude and longitude coordinates. The API analyzes the roof geometry and returns data required to design and visualize solar panel installations and even more.
The API returns structured data that includes:
- Detected roof segments with boundary polygons
- Roof orientation data, including tilt and azimuth
- Candidate solar panel placements in portrait and landscape orientations
- Rooftop obstacle detection to avoid blocked areas
- Optional solar production metrics (flux values) for panel placement evaluation
- Normalized coordinates for rendering the layout on top of the provided map imagery
Base URL
https://api.solargenix.ai
Authentication
All requests to the roof layout API require an access token.
Send the token in the Token header:
Token: <your_access_token>
Access Token Generation
Access tokens can be generated from the Developer page on the SolarGenix application website.
Token issuance is managed in the SolarGenix interface and is not exposed as a public API endpoint.
Token generation flow
- Sign in to the SolarGenix interface.
- Open the Developer page.
- Select Generate Token.
- Copy the generated token and store it securely.
- Use the token in the
Token request header for all public API calls.
Token handling requirements
- Store tokens on your server side only.
- Do not expose tokens in client-side JavaScript, mobile bundles, or public repositories.
- Rotate the token immediately if it is exposed.
- Use a different token for each environment when possible.
Endpoint
POST /v1/layout/
Generates a roof layout and candidate panel placements for the requested property.
Full URL:
https://api.solargenix.ai/v1/layout/
| Header | Required | Value | Description |
|---|
Token | Yes | string | Public API access token generated in the SolarGenix Developer page |
Content-Type | Yes | application/json | Request payload format |
Request Body
| Field | Type | Required | Description |
|---|
lat | number | Yes | Latitude of the property |
lng | number | Yes | Longitude of the property |
measurement_system | string | Yes | Unit system for all dimensional input values. Allowed values: metric, imperial |
panel_size_w | number | Yes | Panel width in the selected measurement system |
panel_size_h | number | Yes | Panel height in the selected measurement system |
setback | object | Yes | Required roof-edge setback configuration |
setback.eave | number | Yes | Setback from eave edges |
setback.ridge | number | Yes | Setback from ridge edges |
setback.hipvalley | number | Yes | Setback from hip and valley edges |
setback.rake | number | Yes | Setback from rake edges |
panel_spacing | number | Yes | Spacing between adjacent panels in the selected measurement system |
calculate_production | boolean | Yes | When true, panel candidates include production-related values such as flux |
Measurement Rules
- When
measurement_system is metric, all dimensional request values must be sent in meters.
- When
measurement_system is imperial, all dimensional request values must be sent in feet.
- Use one system consistently for
panel_size_w, panel_size_h, all setback values, and panel_spacing.
Request Example
curl --request POST "https://api.solargenix.ai/v1/layout/" \
--header "Token: sgx_live_xxxxxxxxxxxxxxxxxxxx" \
--header "Content-Type: application/json" \
--data '{
"lat": 33.1399,
"lng": -117.1661,
"measurement_system": "metric",
"panel_size_w": 1.72,
"panel_size_h": 1.13,
"setback": {
"eave": 0.3,
"ridge": 0.45,
"hipvalley": 0.45,
"rake": 0.9
},
"panel_spacing": 0.04,
"calculate_production": true
}'
JavaScript Example
const response = await fetch("https://api.solargenix.ai/v1/layout/", {
method: "POST",
headers: {
"Content-Type": "application/json",
Token: "sgx_live_xxxxxxxxxxxxxxxxxxxx",
},
body: JSON.stringify({
lat: 33.1399,
lng: -117.1661,
measurement_system: "metric",
panel_size_w: 1.72,
panel_size_h: 1.13,
setback: {
eave: 0.3,
ridge: 0.45,
hipvalley: 0.45,
rake: 0.9,
},
panel_spacing: 0.04,
calculate_production: true,
}),
});
const layout = await response.json();
Success Response
The API returns a JSON object containing the source image and all detected roof geometry required to render candidate panel placements.
{
"map_image": "https://app.solargenix.ai/v1/geoTiff:get?id=OTgyOTliMjhlMTNjN2RhYWQwYjI0N2Q1NDBmZGY3MTgtNmYzMTZmYTgzN2I4NmYxZGNhYzlmYzZiNDBlMzJkNTA6UkdCOkxPVw&key=AIzaSyB0wHitfUdbRICV2MG-_Az0SV1L-DRZwHU",
"obstacles": [
{
"y": 0.6622347235679626,
"x": 0.6092343330383301,
"size": 0.002371065318584442
},
{
"y": 0.5262547731399536,
"x": 0.4840320944786072,
"size": 0.005819257814437151
}
],
"panel_size": [
0.04540977758705369,
0.02983316783335504
],
"roof_segments": [
{
"cycle": [
{ "y": 0.213, "x": 0.308 },
{ "y": 0.401, "x": 0.349 },
{ "y": 0.547, "x": 0.589 },
{ "y": 0.505, "x": 0.787 },
{ "y": 0.391, "x": 0.589 },
{ "y": 0.411, "x": 0.568 },
{ "y": 0.422, "x": 0.495 },
{ "y": 0.390, "x": 0.453 },
{ "y": 0.275, "x": 0.412 }
],
"angle": -148.6864567298103,
"azimuth": 31.925055,
"tilt": 20.933521,
"panels_portrait": [
{
"y": 0.4809831936078284,
"x": 0.6885589416769791,
"flux": 2758.5617769042965
},
{
"y": 0.4649294207721041,
"x": 0.6621691781114049,
"flux": 2758.9307097656247
}
],
"panels_landscape": [
{
"y": 0.47785912967572686,
"x": 0.7048290301834498,
"flux": 2711.016651708984
},
{
"y": 0.478417337821471,
"x": 0.650101228497473,
"flux": 2802.8145025390622
}
]
}
]
}
Response Field Reference
Root Object
| Field | Type | Description |
|---|
map_image | string | URL of the source map or imagery used for roof layout rendering |
obstacles | array<object> | Detected rooftop obstructions that should be avoided during placement |
panel_size | array<number, number> | Normalized panel width and height used for rendering over map_image |
roof_segments | array<object> | Detected roof planes with boundaries, orientation data, and candidate panel placements |
obstacles[]
| Field | Type | Description |
|---|
x | number | Horizontal position of the obstacle in normalized image coordinates |
y | number | Vertical position of the obstacle in normalized image coordinates |
size | number | Relative obstacle footprint size in normalized image coordinates |
roof_segments[]
| Field | Type | Description |
|---|
cycle | array<object> | Closed polygon describing the roof segment boundary |
angle | number | Rotation angle used for segment-aligned panel placement calculations |
azimuth | number | Compass direction of the roof surface in degrees |
tilt | number | Roof tilt in degrees |
panels_portrait | array<object> | Candidate panel centers for portrait orientation |
panels_landscape | array<object> | Candidate panel centers for landscape orientation |
roof_segments[].cycle[]
| Field | Type | Description |
|---|
x | number | Horizontal position of a boundary point in normalized image coordinates |
y | number | Vertical position of a boundary point in normalized image coordinates |
roof_segments[].panels_portrait[]
| Field | Type | Description |
|---|
x | number | Horizontal center position of the candidate panel in normalized image coordinates |
y | number | Vertical center position of the candidate panel in normalized image coordinates |
flux | number | Production-related solar flux value for the panel candidate. Present when calculate_production is enabled |
roof_segments[].panels_landscape[]
| Field | Type | Description |
|---|
x | number | Horizontal center position of the candidate panel in normalized image coordinates |
y | number | Vertical center position of the candidate panel in normalized image coordinates |
flux | number | Production-related solar flux value for the panel candidate. Present when calculate_production is enabled |
Coordinate System and Rendering Rules
The response uses normalized image coordinates for roof layout rendering.
x and y values are relative to the image and typically fall in the range 0.0 to 1.0.
panel_size is also normalized and must be converted before rendering.
cycle, obstacles, panels_portrait, and panels_landscape all use the same normalized coordinate system.
Pixel conversion
To draw the result on top of the returned map_image, convert coordinates using the final rendered image dimensions:
x_px = x * image_width
y_px = y * image_height
panel_width_px = panel_size[0] * image_width
panel_height_px = panel_size[1] * image_height
Important note
Do not treat response placement coordinates as raw pixels. They are normalized placement values intended to be scaled against the final image size.
Common Implementation Notes
- Use
panels_portrait when you want portrait panel candidate placement.
- Use
panels_landscape when you want landscape panel candidate placement.
- Use
flux to rank panel candidate placements when production scoring is enabled.
- Use
cycle to draw roof segments.
- Use
obstacles to block placements or visually mark non-usable rooftop areas.
HTTP Status Expectations
| Status | Meaning |
|---|
200 OK | Layout generated successfully |
400 Bad Request | Request body is invalid or required values are missing |
401 Unauthorized | Token header is missing or invalid |
422 Unprocessable Entity | The property could not be processed into a usable roof layout |
500 Internal Server Error | Unexpected processing failure |
Example Error Responses
Missing or invalid token
{
"error": {
"code": "invalid_token",
"message": "The provided API token is missing, invalid, or expired."
}
}
Invalid request body
{
"error": {
"code": "validation_error",
"message": "measurement_system must be one of: metric, imperial."
}
}
Layout could not be generated
{
"error": {
"code": "layout_unavailable",
"message": "A usable roof layout could not be generated for the requested location."
}
}