Skip to main content
This document describes the public layout API used to generate a roof layout from latitude and longitude coordinates.

Base URL

https://api.solargenix.ai

Authentication

All requests to the public layout API require an access token. Send the token in the Token header:
Token: <your_access_token>

Access Token Generation

Access tokens are generated from the SolarGenix Developer page. Token issuance is managed in the SolarGenix interface and is not exposed as a public API endpoint.

Token generation flow

  1. Sign in to the SolarGenix interface.
  2. Open the Developer page.
  3. Select Generate Token.
  4. Copy the generated token and store it securely.
  5. 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/

Request Headers

HeaderRequiredValueDescription
TokenYesstringPublic API access token generated in the SolarGenix Developer page
Content-TypeYesapplication/jsonRequest payload format

Request Body

FieldTypeRequiredDescription
latnumberYesLatitude of the property
lngnumberYesLongitude of the property
measurement_systemstringYesUnit system for all dimensional input values. Allowed values: metric, imperial
panel_size_wnumberYesPanel width in the selected measurement system
panel_size_hnumberYesPanel height in the selected measurement system
setbackobjectYesRequired roof-edge setback configuration
setback.eavenumberYesSetback from eave edges
setback.ridgenumberYesSetback from ridge edges
setback.hipvalleynumberYesSetback from hip and valley edges
setback.rakenumberYesSetback from rake edges
panel_spacingnumberYesSpacing between adjacent panels in the selected measurement system
calculate_productionbooleanYesWhen 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

FieldTypeDescription
map_imagestringURL of the source map or imagery used for layout rendering
obstaclesarray<object>Detected rooftop obstructions that should be avoided during placement
panel_sizearray<number, number>Normalized panel width and height used for rendering over map_image
roof_segmentsarray<object>Detected roof planes with boundaries, orientation data, and candidate panel placements

obstacles[]

FieldTypeDescription
xnumberHorizontal position of the obstacle in normalized image coordinates
ynumberVertical position of the obstacle in normalized image coordinates
sizenumberRelative obstacle footprint size in normalized image coordinates

roof_segments[]

FieldTypeDescription
cyclearray<object>Closed polygon describing the roof segment boundary
anglenumberRotation angle used for segment-aligned panel placement calculations
azimuthnumberCompass direction of the roof surface in degrees
tiltnumberRoof tilt in degrees
panels_portraitarray<object>Candidate panel centers for portrait orientation
panels_landscapearray<object>Candidate panel centers for landscape orientation

roof_segments[].cycle[]

FieldTypeDescription
xnumberHorizontal position of a boundary point in normalized image coordinates
ynumberVertical position of a boundary point in normalized image coordinates

roof_segments[].panels_portrait[]

FieldTypeDescription
xnumberHorizontal center position of the candidate panel in normalized image coordinates
ynumberVertical center position of the candidate panel in normalized image coordinates
fluxnumberProduction-related solar flux value for the panel candidate. Present when calculate_production is enabled

roof_segments[].panels_landscape[]

FieldTypeDescription
xnumberHorizontal center position of the candidate panel in normalized image coordinates
ynumberVertical center position of the candidate panel in normalized image coordinates
fluxnumberProduction-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 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 candidate placement.
  • Use panels_landscape when you want landscape candidate placement.
  • Use flux to rank candidate placements when production scoring is enabled.
  • Use cycle to draw or clip the roof segment boundary.
  • Use obstacles to block placements or visually mark non-usable rooftop areas.

HTTP Status Expectations

StatusMeaning
200 OKLayout generated successfully
400 Bad RequestRequest body is invalid or required values are missing
401 UnauthorizedToken header is missing or invalid
422 Unprocessable EntityThe property could not be processed into a usable roof layout
500 Internal Server ErrorUnexpected 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."
  }
}