API Documentation
Programmatic access to Azuce solar production forecasting. Generate accurate kWh estimates for any location worldwide.
REST API
Simple JSON request/response over HTTPS
Global Coverage
Satellite irradiance data for any coordinate on Earth
500 Free Calls
Per month, then $0.001 USD per call
Overview
The Azuce Forecasting API provides programmatic access to our physics-based solar production forecasting engine. Using satellite-derived irradiance data and real-time meteorological analysis, the API generates monthly and annual kWh production estimates with conservative, expected, and optimistic ranges.
The API is ideal for solar installers, energy platforms, and developers who need to integrate accurate solar production estimates into their own applications, CRM systems, or proposal tools.
Key capabilities:
- Monthly and annual kWh production estimates for any global location
- Conservative, expected, and optimistic production ranges (±10%)
- Real-time weather conditions and forecast notes
- Optional financial analysis (payback period, 25-year ROI, savings)
- Optional carbon impact analysis (CO2 avoided, equivalents)
- Per-request usage tracking and billing transparency
Authentication
All API requests require an API key for authentication. You can generate API keys from your API Access dashboard.
Include your API key in every request using one of two methods:
Authorization Header (recommended)
Authorization: Bearer azk_your_api_key_hereX-API-Key Header
x-api-key: azk_your_api_key_hereKeep your API keys secure
- Never expose API keys in client-side code or public repositories
- Store keys in environment variables or a secrets manager
- Your full API key is shown only once at creation - store it immediately
- Revoke compromised keys instantly from the API Access dashboard
Base URL
https://azuce.com/api/v1All endpoints are relative to this base URL. The API uses HTTPS exclusively.
Endpoints
POST /forecast
Generate a solar production forecast for a given location and system configuration. Returns monthly kWh estimates, annual totals with conservative/optimistic ranges, and current weather conditions.
POST https://azuce.com/api/v1/forecast
Content-Type: application/json
Authorization: Bearer azk_your_api_key_here
{
"latitude": 51.5074,
"longitude": -0.1278,
"systemSizeKw": 4.0,
"panelAzimuth": 180,
"panelTilt": 35
}GET /forecast
Returns API endpoint information, available fields, and current pricing. No authentication required.
GET https://azuce.com/api/v1/forecastRequest Parameters
Send parameters as a JSON body with Content-Type: application/json.
System Configuration (required)
| Parameter | Type | Status | Default | Description |
|---|---|---|---|---|
latitude | number | Required | Latitude of the installation site. Range: -90 to 90. | |
longitude | number | Required | Longitude of the installation site. Range: -180 to 180. | |
systemSizeKw | number | Required | Total system capacity in kilowatts (kWp). Range: 0.1 to 10,000. | |
panelAzimuth | number | Required | Panel compass direction in degrees. 0 = North, 90 = East, 180 = South, 270 = West. Range: 0 to 360. | |
panelTilt | number | Required | Panel angle from horizontal in degrees. 0 = flat, 90 = vertical. Range: 0 to 90. |
System Tuning (optional)
| Parameter | Type | Status | Default | Description |
|---|---|---|---|---|
shadingLoss | number | Optional | 0 | Shading loss percentage. Accounts for nearby obstructions (trees, buildings). Range: 0 to 30. |
systemLosses | number | Optional | 14 | Total system losses percentage. Includes wiring, inverter, soiling, mismatch losses. Range: 0 to 50. |
tempCoefficient | number | Optional | -0.35 | Temperature coefficient of power (%/°C). Typical range: -0.5 to -0.3 for crystalline silicon. Range: -1 to 0. |
address | string | Optional | Human-readable address for the installation site. Stored for reference only, does not affect calculations. | |
customerName | string | Optional | Customer or project name for reference. Does not affect calculations. |
Financial Analysis (optional)
Set enableFinancials: true to include a financialAnalysis object in the response with savings, payback period, 25-year ROI, and yearly breakdown.
| Parameter | Type | Status | Default | Description |
|---|---|---|---|---|
enableFinancials | boolean | Optional | false | Enable financial analysis in the forecast result. |
installedCost | number | Optional | Total installed cost of the solar system in the specified currency. | |
electricityRate | number | Optional | Electricity purchase rate per kWh in the specified currency. | |
exportRate | number | Optional | Feed-in / export tariff per kWh in the specified currency. | |
selfConsumptionPct | number | Optional | Estimated percentage of generated energy consumed on-site. Range: 0 to 100. | |
annualMaintenanceCost | number | Optional | Annual maintenance cost in the specified currency. | |
annualDegradationPct | number | Optional | Annual panel degradation rate. Typical: 0.5-0.7%. Range: 0 to 5. |
Carbon Impact (optional)
Set enableCarbon: true to include a carbonImpact object in the response with CO2 avoided, driving equivalents, and tree equivalents.
| Parameter | Type | Status | Default | Description |
|---|---|---|---|---|
enableCarbon | boolean | Optional | false | Enable carbon impact analysis in the forecast result. |
gridKgCo2PerKwh | number | Optional | Grid carbon intensity in kg CO2 per kWh. Auto-detected by country if not provided. |
Locale & Currency (optional)
| Parameter | Type | Status | Default | Description |
|---|---|---|---|---|
currencyCode | string | Optional | USD | ISO 4217 currency code (e.g., "GBP", "EUR", "JPY"). Used for financial output formatting. |
currencySymbol | string | Optional | $ | Currency symbol for display (e.g., "£", "€", "¥"). |
countryCode | string | Optional | US | ISO 3166-1 alpha-2 country code. Used for auto-detecting carbon intensity and energy rates. |
Response Format
All responses are JSON. Successful forecasts return HTTP 200 with the following structure:
Success Response (200)
{
"forecast": {
"monthlyKwh": [
120.5, 145.2, 210.8, 280.3, 340.1,
365.7, 370.2, 345.6, 270.4, 195.3,
135.6, 105.8
],
"annualKwh": 2885.5,
"conservativeAnnual": 2597.0,
"optimisticAnnual": 3174.1,
"weatherNote": "Current conditions: partly cloudy, 18°C...",
"modelVersion": "1.0.0",
"location": {
"latitude": 51.5074,
"longitude": -0.1278,
"address": "London, UK"
},
"system": {
"systemSizeKw": 4.0,
"panelAzimuth": 180,
"panelTilt": 35,
"shadingLoss": 0,
"systemLosses": 14
}
},
"financialAnalysis": {
"annualSavings": 242.38,
"annualExportIncome": 100.99,
"annualMaintenanceCost": 150,
"annualNetBenefit": 193.37,
"simplePaybackYears": 10.34,
"totalBenefit25Years": 4381.52,
"roi25YearPercent": 119.08,
"selfConsumption": {
"selfUsedKwh": 865.65,
"exportedKwh": 2019.85,
"selfConsumptionPercent": 30
},
"inputs": {
"installedCost": 2000,
"electricityRate": 0.28,
"exportRate": 0.05,
"selfConsumptionPct": 30,
"annualMaintenanceCost": 150,
"annualDegradationPct": 0.5
},
"yearlyBreakdown": [
{ "year": 1, "productionKwh": 2885.5, "netBenefit": 193.37, "cumulativeBenefit": 193.37 },
{ "year": 2, "productionKwh": 2871.07, "netBenefit": 191.65, "cumulativeBenefit": 385.02 }
]
},
"carbonImpact": {
"annualCo2AvoidedKg": 672.32,
"equivalentMilesDriven": 1664,
"equivalentTreesPlanted": 32.02,
"gridKgCo2PerKwh": 0.233,
"lifetimeCo2AvoidedKg": 16808.0
},
"usage": {
"callsThisMonth": 42,
"freeCallsRemaining": 458,
"billableCallsThisMonth": 0,
"estimatedCostUsd": 0
}
}The financialAnalysis object is included only when enableFinancials: true is set. The carbonImpact object is included only when enableCarbon: true is set. The yearlyBreakdown array contains all 25 years (truncated above for brevity).
Response Fields
| Field | Type | Description |
|---|---|---|
| forecast.monthlyKwh | number[12] | Estimated kWh production for each month (Jan-Dec) |
| forecast.annualKwh | number | Expected annual production in kWh |
| forecast.conservativeAnnual | number | Conservative estimate (-10% from expected) |
| forecast.optimisticAnnual | number | Optimistic estimate (+10% from expected) |
| forecast.weatherNote | string | Human-readable weather conditions at the site |
| forecast.modelVersion | string | Version of the forecasting model used |
| forecast.location | object | Echo of input coordinates and address |
| forecast.system | object | Echo of system configuration used |
| Financial Analysis (when enableFinancials: true) | ||
| financialAnalysis.annualSavings | number | Annual savings from self-consumed energy |
| financialAnalysis.annualExportIncome | number | Annual income from exported energy |
| financialAnalysis.annualNetBenefit | number | Net annual benefit (savings + export - maintenance) |
| financialAnalysis.simplePaybackYears | number | null | Simple payback period in years (null if not calculable) |
| financialAnalysis.totalBenefit25Years | number | Total benefit over 25 years with degradation |
| financialAnalysis.roi25YearPercent | number | null | 25-year return on investment as percentage |
| financialAnalysis.selfConsumption | object | Breakdown of self-used vs exported kWh |
| financialAnalysis.inputs | object | Echo of financial input parameters used (with defaults) |
| financialAnalysis.yearlyBreakdown | array[25] | Year-by-year production, net benefit, and cumulative benefit |
| Carbon Impact (when enableCarbon: true) | ||
| carbonImpact.annualCo2AvoidedKg | number | Annual CO2 emissions avoided in kilograms |
| carbonImpact.equivalentMilesDriven | number | Equivalent car miles offset annually |
| carbonImpact.equivalentTreesPlanted | number | Equivalent trees planted (10-year absorption) |
| carbonImpact.gridKgCo2PerKwh | number | Grid carbon intensity used for calculation |
| carbonImpact.lifetimeCo2AvoidedKg | number | Estimated 25-year lifetime CO2 avoided |
| Usage | ||
| usage.callsThisMonth | number | Total API calls made this billing period |
| usage.freeCallsRemaining | number | Remaining free calls this month (out of 500) |
| usage.billableCallsThisMonth | number | Calls exceeding the free tier this month |
| usage.estimatedCostUsd | number | Estimated charges in USD for billable calls |
Error Handling
The API uses standard HTTP status codes. Error responses include a JSON body with error and message fields.
| Status | Error | Description |
|---|---|---|
| 200 | - | Success. Forecast generated. |
| 400 | Validation Error | Invalid input parameters. Check the details array for specific field errors. |
| 401 | Unauthorized | Missing, invalid, or revoked API key. |
| 429 | Rate Limited | External data source temporarily rate-limited. Retry after a few seconds. |
| 500 | Internal Server Error | Server-side issue. Retry or contact support. |
401 Unauthorized
{
"error": "Unauthorized",
"message": "Invalid or missing API key. Include your key via Authorization: Bearer <key> or x-api-key header."
}400 Validation Error
{
"error": "Validation Error",
"message": "Invalid input parameters",
"details": [
{ "field": "latitude", "message": "Number must be greater than or equal to -90" },
{ "field": "systemSizeKw", "message": "Required" }
]
}429 Rate Limited
{
"error": "Rate Limited",
"message": "External data source is temporarily rate-limited. Please retry in a few seconds."
}Rate Limits
The API itself does not impose hard rate limits on requests per second. However, the underlying satellite irradiance and weather data sources have their own rate limits. If you encounter a 429 response, implement exponential backoff:
// Exponential backoff example
const delays = [1000, 2000, 4000, 8000]; // milliseconds
for (const delay of delays) {
const response = await fetch(url, options);
if (response.status !== 429) break;
await new Promise(r => setTimeout(r, delay));
}Best practices for high-volume usage:
- Cache results for the same coordinates - irradiance data changes slowly
- Space requests 200-500ms apart for batch processing
- Satellite irradiance data is cached for 180 days on our servers
- Weather data is refreshed every 6 hours
Pricing & Billing
500
API calls per month at no charge. Resets on the 1st of each month.
$0.001 USD / call
Billed via Stripe metered billing. Enable billing from the API Access page.
| Monthly Calls | Cost (USD) |
|---|---|
| 500 | $0.00 (free) |
| 1,000 | $0.50 |
| 5,000 | $4.50 |
| 10,000 | $9.50 |
| 50,000 | $49.50 |
| 100,000 | $99.50 |
All API billing is in USD. Usage is tracked per API key and aggregated monthly for billing purposes. You can monitor real-time usage from the API Access dashboard.
Code Examples
cURL
curl -X POST https://azuce.com/api/v1/forecast \
-H "Content-Type: application/json" \
-H "Authorization: Bearer azk_your_api_key_here" \
-d '{
"latitude": 51.5074,
"longitude": -0.1278,
"systemSizeKw": 4.0,
"panelAzimuth": 180,
"panelTilt": 35
}'Python
import requests
API_KEY = "azk_your_api_key_here"
URL = "https://azuce.com/api/v1/forecast"
response = requests.post(
URL,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}",
},
json={
"latitude": 51.5074,
"longitude": -0.1278,
"systemSizeKw": 4.0,
"panelAzimuth": 180,
"panelTilt": 35,
},
)
data = response.json()
forecast = data["forecast"]
print(f"Annual Production: {forecast['annualKwh']:.0f} kWh")
print(f"Range: {forecast['conservativeAnnual']:.0f} - {forecast['optimisticAnnual']:.0f} kWh")
print(f"Monthly: {[round(m) for m in forecast['monthlyKwh']]}")
print(f"Weather: {forecast['weatherNote']}")JavaScript / Node.js
const API_KEY = "azk_your_api_key_here";
const response = await fetch("https://azuce.com/api/v1/forecast", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`,
},
body: JSON.stringify({
latitude: 51.5074,
longitude: -0.1278,
systemSizeKw: 4.0,
panelAzimuth: 180,
panelTilt: 35,
}),
});
const data = await response.json();
console.log("Annual:", data.forecast.annualKwh, "kWh");
console.log("Conservative:", data.forecast.conservativeAnnual, "kWh");
console.log("Optimistic:", data.forecast.optimisticAnnual, "kWh");
console.log("Monthly:", data.forecast.monthlyKwh);
console.log("Usage:", data.usage.callsThisMonth, "/", 500, "free calls used");PHP
<?php
$apiKey = "azk_your_api_key_here";
$ch = curl_init("https://azuce.com/api/v1/forecast");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer $apiKey",
],
CURLOPT_POSTFIELDS => json_encode([
"latitude" => 51.5074,
"longitude" => -0.1278,
"systemSizeKw" => 4.0,
"panelAzimuth" => 180,
"panelTilt" => 35,
]),
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
$forecast = $data["forecast"];
echo "Annual: " . round($forecast["annualKwh"]) . " kWh\n";
echo "Range: " . round($forecast["conservativeAnnual"]) . " - " . round($forecast["optimisticAnnual"]) . " kWh\n";Financial Analysis Request
curl -X POST https://azuce.com/api/v1/forecast \
-H "Content-Type: application/json" \
-H "Authorization: Bearer azk_your_api_key_here" \
-d '{
"latitude": 51.5074,
"longitude": -0.1278,
"systemSizeKw": 4.0,
"panelAzimuth": 180,
"panelTilt": 35,
"enableFinancials": true,
"installedCost": 8000,
"electricityRate": 0.28,
"exportRate": 0.05,
"selfConsumptionPct": 40,
"annualDegradationPct": 0.5,
"currencyCode": "GBP",
"currencySymbol": "£",
"countryCode": "GB",
"enableCarbon": true,
"gridKgCo2PerKwh": 0.233
}'Batch Processing Example
import requests
import time
import json
API_KEY = "azk_your_api_key_here"
URL = "https://azuce.com/api/v1/forecast"
sites = [
{"name": "London Office", "lat": 51.5074, "lng": -0.1278},
{"name": "Berlin Warehouse", "lat": 52.5200, "lng": 13.4050},
{"name": "Madrid Factory", "lat": 40.4168, "lng": -3.7038},
{"name": "Sydney HQ", "lat": -33.8688, "lng": 151.2093},
]
results = []
for site in sites:
response = requests.post(
URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"latitude": site["lat"],
"longitude": site["lng"],
"systemSizeKw": 10.0,
"panelAzimuth": 180,
"panelTilt": 30,
},
)
if response.status_code == 429:
time.sleep(5) # Retry after rate limit
response = requests.post(URL, headers={"Authorization": f"Bearer {API_KEY}"}, json={...})
data = response.json()
results.append({
"site": site["name"],
"annual_kwh": data["forecast"]["annualKwh"],
"range": f"{data['forecast']['conservativeAnnual']:.0f}-{data['forecast']['optimisticAnnual']:.0f}",
})
time.sleep(0.3) # Space out requests
for r in results:
print(f"{r['site']}: {r['annual_kwh']:.0f} kWh ({r['range']} kWh)")Data Sources & Methodology
The forecasting engine uses physics-based calculations with real-world data inputs:
Satellite Irradiance Data
Monthly Global Horizontal Irradiance (GHI) and temperature data derived from satellite observations. Represents long-term climatological averages. Cached for 180 days for consistent results.
Meteorological Forecasts
Real-time weather data including cloud cover, temperature, and short-term forecasts. Refreshed every 6 hours for up-to-date weather notes in the response.
Physics-Based Model (v1.0.0)
Calculates Plane of Array (POA) factor based on tilt and azimuth, applies temperature derating, system losses, and shading factors. Conservative/optimistic ranges use ±10% from the expected value.
For detailed methodology, see the Forecasting Methodology page.
Changelog
v1.1.0 - Financial & Carbon in API Response
- Financial analysis now returned in API response (savings, payback, 25-year ROI, yearly breakdown)
- Carbon impact now returned in API response (CO2 avoided, driving/tree equivalents)
- New response fields:
financialAnalysis,carbonImpact
v1.0.0 - Initial Release
- Solar production forecasting via REST API
- API key authentication with SHA-256 hashing
- Monthly and annual kWh estimates with ±10% ranges
- Optional financial analysis and carbon impact parameters
- 500 free calls/month with metered billing overage
- Real-time weather notes and conditions
- Global coverage with satellite irradiance data
- Per-request usage tracking
