v1STABLE

API Documentation

The SunTrace3D Partner API lets you generate HD 3D city models, calculate solar energy yield, and embed interactive 3D viewers on your website. All endpoints use JSON and standard HTTP methods.

1

Overview

The SunTrace3D API is a RESTful service for programmatic access to 3D city model generation and solar energy calculations. The API is designed for partners who want to integrate solar analysis into their own applications, websites, or workflows.

Base URL

https://suntrace3d.com/api/v1
REST API
JSON request/response
Bearer Auth
API key authentication
HD Quality
All API models are HD

Available Endpoints

POST/api/v1/modelsGenerate a new HD 3D model
GET/api/v1/models/:idCheck model generation status
POST/api/solar/calculateCalculate solar energy yield
GET/embedEmbeddable 3D viewer (iframe)
GET/api/healthHealth check (no auth required)
Partner portal showing API keys and usage statistics
The Partner Portal — manage API keys, view usage statistics, and get embed code
2

Authentication

All API requests require authentication via a Bearer token in the Authorization header. API keys are managed through the Partner Portal.

Getting an API key

  1. 1
    Create an account
    Sign up at /auth/signup if you haven't already.
  2. 2
    Upgrade to Business
    A Business subscription (€99/month) is required for API access. Upgrade from your account settings or the pricing page.
  3. 3
    Generate an API key
    Visit the Partner Portal and click "Create Key". Copy your key immediately — it won't be shown again.
  4. 4
    Use in requests
    Include the key in all API requests as a Bearer token.
Authentication Headerbash
curl -H "Authorization: Bearer st_live_abc123def456..." \
  https://suntrace3d.com/api/v1/models

Keep your API key secret

Never expose your API key in client-side JavaScript, public repositories, or front-end code. If your key is compromised, revoke it immediately from the Partner Portal and create a new one.

3

Generate a 3D Model

Request the generation of an HD 3D city model for a specific geographic location. The model is generated asynchronously — poll the status endpoint to check when it's ready.

POST/api/v1/models

Request Body

latitudenumberrequiredLatitude of the center point (-90 to 90)
longitudenumberrequiredLongitude of the center point (-180 to 180)
radiusKmnumberRadius of the area to model in km (default: 0.3)

Response

idstringrequiredUnique model identifier for status polling
statusstringrequired"pending" | "processing" | "ready" | "failed"
modelUrlstringURL to the GLB model file (when ready)
progressnumberGeneration progress 0-100 (when processing)
stepstringCurrent generation step description
Requestbash
curl -X POST https://suntrace3d.com/api/v1/models \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "latitude": 44.8699,
    "longitude": 13.8420,
    "radiusKm": 0.3
  }'
Response (pending)json
{
  "id": "hd_44.8699_13.8420_0.3",
  "status": "pending"
}
Response (ready)json
{
  "id": "hd_44.8699_13.8420_0.3",
  "status": "ready",
  "modelUrl": "https://s3.eu-central-1.amazonaws.com/suntrace-models/hd_44.8699_13.8420_0.3/scene.glb"
}

Model caching

If a model for the same location and radius has already been generated, the API returns the cached result immediately with status: "ready". Models are cached in S3 for 30 days. You are not charged for cached results.

API request generating a 3D model
The API generates HD 3D models asynchronously — poll the status endpoint until ready
4

Check Model Status

Poll this endpoint to check the status of a model generation request. The model goes through several stages: pending → processing → ready.

GET/api/v1/models/:id
Requestbash
curl https://suntrace3d.com/api/v1/models/hd_44.8699_13.8420_0.3 \
  -H "Authorization: Bearer YOUR_API_KEY"
Response (processing)json
{
  "id": "hd_44.8699_13.8420_0.3",
  "status": "processing",
  "progress": 65,
  "step": "Generating textures..."
}
Response (ready)json
{
  "id": "hd_44.8699_13.8420_0.3",
  "status": "ready",
  "modelUrl": "https://s3.eu-central-1.amazonaws.com/suntrace-models/hd_44.8699_13.8420_0.3/scene.glb",
  "progress": 100,
  "step": null
}

Status Values

pendingJob is queued and waiting to be picked up by a worker
processingModel is being generated. Check progress field for percentage.
readyModel is ready. The modelUrl field contains the download URL.
failedGeneration failed. You can retry by creating a new request.

Polling recommendation

We recommend polling every 5-10 seconds. Typical generation times are 30-120 seconds depending on the area size and server load. The progress field provides a percentage (0-100) to show a progress indicator in your UI.

5

Calculate Solar Energy

Calculate annual solar energy yield for a specific panel configuration and location. This endpoint uses PVGIS (Photovoltaic Geographical Information System) satellite data for accurate irradiance values.

POST/api/solar/calculate

Request Body

latitudenumberrequiredLocation latitude
longitudenumberrequiredLocation longitude
tiltDegnumberrequiredPanel tilt angle in degrees (0-90)
azimuthDegnumberrequiredPanel azimuth in degrees (0=North, 180=South)
panelAreaM2numberrequiredTotal panel area in square meters
panelEfficiencynumberrequiredPanel efficiency (0.0 - 1.0, typically 0.18-0.22)
shadingLossFractionnumberShading loss factor (0.0-1.0, default: 0)

Response

annualYieldKwhnumberrequiredEstimated annual energy yield in kWh
peakPowerKwnumberrequiredPeak power output in kW
specificYieldnumberrequiredSpecific yield in kWh/kWp
monthlyKwhnumber[]requiredArray of 12 monthly kWh values
sourcestringrequiredData source identifier ("pvgis")
Requestbash
curl -X POST https://suntrace3d.com/api/solar/calculate \
  -H "Content-Type: application/json" \
  -d '{
    "latitude": 44.8699,
    "longitude": 13.8420,
    "tiltDeg": 35,
    "azimuthDeg": 180,
    "panelAreaM2": 20,
    "panelEfficiency": 0.20,
    "shadingLossFraction": 0.05
  }'
Responsejson
{
  "annualYieldKwh": 4982,
  "peakPowerKw": 4.0,
  "specificYield": 1246,
  "monthlyKwh": [248, 305, 412, 465, 522, 548, 562, 530, 445, 368, 280, 232],
  "source": "pvgis"
}

No authentication required

The solar calculation endpoint is publicly available and does not require an API key. It uses the PVGIS public API maintained by the European Commission's Joint Research Centre.

Solar energy calculation API response
The solar calculation API returns annual yield, peak power, and monthly breakdown
6

Embed Viewer

Embed an interactive 3D solar viewer on your website using an iframe. The embed viewer includes time controls for shadow simulation and works on both desktop and mobile.

Embed URL Parameters

latnumberrequiredLatitude of the location to display
lngnumberrequiredLongitude of the location to display
keystringrequiredYour API key for authentication
Basic Embed Codehtml
<iframe
  src="https://suntrace3d.com/embed?lat=44.8699&lng=13.8420&key=YOUR_API_KEY"
  width="100%"
  height="500"
  frameborder="0"
  allow="fullscreen"
  style="border-radius: 12px; border: 1px solid #e5e7eb;">
</iframe>
Responsive Embed (recommended)html
<div style="position: relative; width: 100%; padding-bottom: 56.25%; overflow: hidden; border-radius: 12px;">
  <iframe
    src="https://suntrace3d.com/embed?lat=44.8699&lng=13.8420&key=YOUR_API_KEY"
    style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;"
    allow="fullscreen">
  </iframe>
</div>

Embed features

Interactive 3D orbit, pan, and zoom
Time slider for shadow simulation
Responsive — works on mobile
Google 3D Tiles photorealistic models
No additional JavaScript required
Fullscreen support
Embedded 3D viewer in an iframe
The embeddable viewer includes time controls and works on both desktop and mobile
7

Rate Limits

The API enforces rate limits to ensure fair usage and system stability.

Model Generation
POST /api/v1/models
10 requests
per hour, per API key
Status Polling
GET /api/v1/models/:id
No limit
Poll as needed
Solar Calculation
POST /api/solar/calculate
No limit
Public endpoint
Embed Views
GET /embed
No limit
Unlimited views
Rate Limit Exceeded Response (429)json
{
  "error": "Rate limit exceeded. Maximum 10 generations per hour."
}
8

Error Handling

The API uses standard HTTP status codes. All error responses include a JSON body with an error field describing the problem.

HTTP Status Codes

200Success — request completed successfully
400Bad Request — missing or invalid parameters
401Unauthorized — missing or invalid API key
404Not Found — model ID does not exist
429Too Many Requests — rate limit exceeded
503Service Unavailable — external service (PVGIS) is down
Error Response Examplejson
{
  "error": "latitude and longitude are required"
}
Authentication Errorjson
{
  "error": "Invalid or revoked API key"
}
9

Webhooks

Webhook support for model completion notifications is planned for a future release. Currently, use polling on the status endpoint to check when models are ready.

Coming Soon

Webhook callbacks will send a POST request to your specified URL when model generation completes, eliminating the need for polling. This feature is on our roadmap.

10

Full Examples

Complete, copy-paste examples for common integration scenarios.

Generate a model and wait for completion

Bash — complete workflowbash
#!/bin/bash
API_KEY="YOUR_API_KEY"
BASE_URL="https://suntrace3d.com"

# 1. Request model generation
echo "Requesting model generation..."
RESPONSE=$(curl -s -X POST "$BASE_URL/api/v1/models" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"latitude": 44.8699, "longitude": 13.8420, "radiusKm": 0.3}')

MODEL_ID=$(echo $RESPONSE | jq -r '.id')
STATUS=$(echo $RESPONSE | jq -r '.status')
echo "Model ID: $MODEL_ID (status: $STATUS)"

# 2. Poll until ready
while [ "$STATUS" != "ready" ] && [ "$STATUS" != "failed" ]; do
  sleep 5
  RESPONSE=$(curl -s "$BASE_URL/api/v1/models/$MODEL_ID" \
    -H "Authorization: Bearer $API_KEY")
  STATUS=$(echo $RESPONSE | jq -r '.status')
  PROGRESS=$(echo $RESPONSE | jq -r '.progress // 0')
  echo "Status: $STATUS ($PROGRESS%)"
done

# 3. Get the model URL
if [ "$STATUS" = "ready" ]; then
  MODEL_URL=$(echo $RESPONSE | jq -r '.modelUrl')
  echo "Model ready: $MODEL_URL"
else
  echo "Generation failed"
fi

JavaScript/Node.js integration

Node.js — generate and polljavascript
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://suntrace3d.com';

async function generateModel(lat, lng) {
  // 1. Request generation
  const res = await fetch(`${BASE_URL}/api/v1/models`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ latitude: lat, longitude: lng }),
  });

  const { id, status, modelUrl } = await res.json();

  // If already cached, return immediately
  if (status === 'ready') return { id, modelUrl };

  // 2. Poll until ready
  return pollStatus(id);
}

async function pollStatus(modelId) {
  while (true) {
    await new Promise(r => setTimeout(r, 5000)); // Wait 5s

    const res = await fetch(`${BASE_URL}/api/v1/models/${modelId}`, {
      headers: { 'Authorization': `Bearer ${API_KEY}` },
    });

    const data = await res.json();
    console.log(`Status: ${data.status} (${data.progress || 0}%)`);

    if (data.status === 'ready') return data;
    if (data.status === 'failed') throw new Error('Generation failed');
  }
}

// Usage
generateModel(44.8699, 13.8420)
  .then(data => console.log('Model URL:', data.modelUrl))
  .catch(err => console.error(err));

Python integration

Python — generate and calculate solarpython
import requests
import time

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://suntrace3d.com"

def generate_model(lat: float, lng: float) -> dict:
    """Generate an HD 3D model and wait for completion."""
    # Request generation
    res = requests.post(
        f"{BASE_URL}/api/v1/models",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"latitude": lat, "longitude": lng, "radiusKm": 0.3},
    )
    data = res.json()

    if data["status"] == "ready":
        return data

    # Poll until ready
    model_id = data["id"]
    while True:
        time.sleep(5)
        res = requests.get(
            f"{BASE_URL}/api/v1/models/{model_id}",
            headers={"Authorization": f"Bearer {API_KEY}"},
        )
        data = res.json()
        print(f"Status: {data['status']} ({data.get('progress', 0)}%)")

        if data["status"] == "ready":
            return data
        if data["status"] == "failed":
            raise Exception("Generation failed")

def calculate_solar(lat: float, lng: float, tilt: float = 35, azimuth: float = 180) -> dict:
    """Calculate solar energy yield for a panel configuration."""
    res = requests.post(
        f"{BASE_URL}/api/solar/calculate",
        json={
            "latitude": lat,
            "longitude": lng,
            "tiltDeg": tilt,
            "azimuthDeg": azimuth,
            "panelAreaM2": 20,
            "panelEfficiency": 0.20,
        },
    )
    return res.json()

# Usage
model = generate_model(44.8699, 13.8420)
print(f"Model URL: {model['modelUrl']}")

solar = calculate_solar(44.8699, 13.8420)
print(f"Annual yield: {solar['annualYieldKwh']} kWh")
print(f"Monthly: {solar['monthlyKwh']}")
API integration code examples in multiple languages
Complete code examples in Bash, JavaScript, and Python for API integration
11

AI Agent Integration

AI agents (chatbots, virtual assistants) can create sessions to redirect users to SunTrace3D with pre-configured Solar Wizard settings and optional automatic roof detection. The 3D model generates when the user opens the link (~1-2 minutes).

Endpoints

POST/api/mcp-sessionsCreate agent session with wizard params
GET/api/mcp-sessions/:idCheck session & model status
POST/api/mcp-sessions

Request Parameters

agentNamestringrequiredAgent identifier (required)
latitudenumberrequiredLocation center latitude
longitudenumberrequiredLocation center longitude
wizardGoalstringWizard goal preset
wizardKwhnumberMonthly kWh for cover_bill
roofLatnumberRoof latitude for auto-click
roofLngnumberRoof longitude for auto-click
POST /api/mcp-sessionsjson
{
  "agentName": "ChatGPT",
  "latitude": 44.8699,
  "longitude": 13.8420,
  "wizardGoal": "cover_bill",
  "wizardKwh": 350,
  "roofLat": 44.8701,
  "roofLng": 13.8418
}
Responsejson
{
  "sessionId": "clxyz...",
  "viewerUrl": "https://suntrace3d.com/viewer?session=clxyz...&lat=44.869900&lng=13.842000&wizard=cover_bill&wizardKwh=350&roofLat=44.8701000&roofLng=13.8418000",
  "status": "created",
  "modelStatus": "not_generated",
  "agentName": "ChatGPT"
}

No pre-generation: Agent sessions do not trigger model generation. The 3D model generates when the user opens the viewer link (~1-2 minutes, loading animation shown). Pro users automatically get HD quality; free users get SD.

Recommended Workflows

With Roof Coordinates
Provide precise roof coordinates for automatic panel placement. Best UX — user clicks link, model loads, panels are placed automatically.
Manual Roof Selection
Let the user pick the exact roof location. The wizard opens and waits for the user to click on their roof.
Direct URL
Construct a viewer URL directly without an API call. Simplest integration, no session tracking.

URL Parameters (Viewer)

wizardstringPre-select wizard goal
wizardKwhnumberMonthly kWh for cover_bill
roofLatnumberAuto-click roof latitude
roofLngnumberAuto-click roof longitude
sessionstringMCP session ID (auto-included by API)

Python Example

Python — create session and send link to userpython
import requests

def create_solar_link(lat, lng, roof_lat=None, roof_lng=None, monthly_kwh=None):
    """Create an agent session and return the viewer URL."""
    payload = {
        "agentName": "MySolarBot",
        "latitude": lat,
        "longitude": lng,
        "wizardGoal": "cover_bill" if monthly_kwh else "maximize_energy",
    }
    if monthly_kwh:
        payload["wizardKwh"] = monthly_kwh
    if roof_lat is not None and roof_lng is not None:
        payload["roofLat"] = roof_lat
        payload["roofLng"] = roof_lng

    res = requests.post("https://suntrace3d.com/api/mcp-sessions", json=payload)
    res.raise_for_status()
    return res.json()["viewerUrl"]

# Usage — send this link to the user
url = create_solar_link(
    lat=44.8699, lng=13.8420,
    roof_lat=44.8701, roof_lng=13.8418,
    monthly_kwh=350,
)
print(f"Send this to your user: {url}")
# User clicks -> model generates (~1-2 min) -> wizard auto-opens -> panels placed

Important Notes

  • Every API request must include an agentName identifying the calling agent. This is required for analytics and usage tracking.
  • roofLat/roofLng should point as precisely as possible to the center of the desired roof surface. The system raycasts downward at that GPS point.
  • When roofLat/roofLng are provided, the system automatically attempts to detect the roof surface at those coordinates. If the auto-detection misses, the user can click manually or use "Start Over".
  • Users can always click "Start Over" to remove auto-placed panels and select a different roof.
  • The Solar Wizard requires a Pro subscription. Free users will see an upgrade prompt.
  • Agent sessions do not pre-generate models. The 3D model generates when the user opens the link (~1-2 minutes). Pro users get HD, free users get SD.

New to SunTrace3D?

Check out the User Guide for a complete walkthrough of the 3D viewer, shadow simulation, and solar panel analysis features.

User Guide