Welcome to the alitiq-Solar-API. The interface to manage and handle solar power forecast for your individual portfolio
Register 📃
To use alitiq's solar API, alitiq will provide you with access credentials consisting of a secret key (x-api-key
for the header ). The secret key must not be made accessible to third parties and must be passed in the header for each request.
Introduction
To receive optimised forecasts, you need to setup
- a PV-System in your portfolio
- provide measurement data of PV system power output (AC) at least 90 days back from now
- Update data at least once a day
Our system will check out the availability. In case no data is provided the arithmetic mean of several forecasts is used under the weather model "optimised".
API-Call
Basic url:
https://solar.alitiq.com/ Show archive.org snapshot
alitiq serves different Endpoints:
-
Configure PV-Systems portfolio :
/pv_systems
-
Adding and inspection of solar power measurement :
/measurement
-
receiving solar power forecast:
/forecast
Authentication 🔒
Authentication is done using the x-api-key
parameter in the header of each request. With the command line interface tool cURL, a request looks like this:
Header:
curl -X GET 'https://solar.alitiq.com/weather/?latitude=49.356&longitude=11.904&response_format=json&weather_model=icon_eu' -H 'x-api-key: <your-api-key>'
The x-api-key
is also used to match you with your portfolio.
1. Setup your portfolio ⚙️ Show archive.org snapshot
The api endpoints to setup your PV-Systems portfolio are:
POST: https://solar.alitiq.com/pv\_systems/add Show archive.org snapshot
POST: https://solar.alitiq.com/pv_systems/delete Show archive.org snapshot
GET: https://solar.alitiq.com/pv_systems/list Show archive.org snapshot
Add
To add pv systems to your portfolio, you have to use the following POST command:
POST: https://solar.alitiq.com/pv_systems/add/ Show archive.org snapshot
In the backend, we use the following form model.
class PvSystemsForm(BaseModel):
"""PvSystems Form data to post new sub systems"""
site_name: str
location_id: str = None
latitude: float
longitude: float
installed_power: float
installed_power_inverter: float
azimuth: float # 180 is South !
tilt: float
temp_factor: float = None
mover: int = None
max_rotation_angle: float = None
row_distance: float = None
do_backtracking: bool = None
table_length: float = None
Each API call represent 1 PV-System with one or multiple subsystems. In the following image you can see a description of tilt and azimuth. In our configuration azimuth equals the orientation.
The following table gives you a detailed description for all required parameters
Parameter | Description | Typ |
---|---|---|
location_id | You have the ability to define your own location_id or use a default one generated by altiq. |
string |
OPTIONAL | ||
site_name | Name of the site, can be an empty string if you do not have one | string |
latitude | WGS84 Coordinate in North-South Direction (e.g. google maps coordinates). No Degree Minutes allowed! | float |
longitude | WGS84 Coordinate in West-East Direction (e.g. google maps coordinates). No Degree Minutes allowed! | float |
response_format | html, csv, json, CSV and JSON are default pandas.DataFrame outputs. | string |
azimuth | Azimuth (or Orientation) of the PV modules in the (Sub-) System. 180° = SOUTH, 90° = EAST, 270°=WEST | float |
tilt | tilt of the pv modules. Typically between 10 to 30 | float |
power | Installed DC Power of PV (Sub-) System | float |
inverter_power | Installed AC Power of PV (Sub-) System (after inverter) | float |
temp_factor | temperature factor to consider reduced ventilation. 0.035 is a typical value for free mounted PV systems 0.05 is typical value for rooftop mounted system | float |
mover | in case the PV System is equipped with a tracking system, the following tracking modes are available: \ 1 NO_TRACKING = 1 (or 0) | |
2 VERTICAL_AXIS_TRACKING = 2 \ 3 HORIZONTAL_AXIS_TRACKING = 3 \ 4 DUAL_AXIS_TRACKING = 4 | integer |
In case mover > 1 additional information is required:
Parameter | Erläuterung | Typ |
---|---|---|
max_rotation_angle | information for single axis tracker | float |
row_distance | distance between pv system mounts in metres | float |
table_length | length of pv module table on the mount | float |
do_backtracking |
True or False True when backtracking is enabled to reduce shading |
bool |
Some important notes:
- Azimuth (=Orientation) SOUTH equals 180° ! West = 90°, East = 270°, North = 0°
- Each POST call equals one individual PV System. Dumping multiple System at once is not supported at the moment.
- The location_id is not required but will be
- Please check your configuration via the list command.
- An update of the existing configuration is not possible at the Moment. DELETE the System and ADD it again.
Example code
curl
curl --request POST \
--url https://solar.alitiq.com/pv_systems/add \
--header 'Content-Type: application/json' \
--header 'x-api-key: {api-key}' \
--data '[
{
"site_name": "test_2",
"latitude": 48.9,
"longitude": 10.3,
"power": 320,
"inverter_power": 300,
"azimuth": 180,
"tilt": 13,
"temp_factor": 0.033,
"mover": 0
},
{
"site_name": "test_2",
"latitude": 48.9,
"longitude": 10.3,
"power": 320,
"inverter_power": 300,
"azimuth": 180,
"tilt": 15,
"temp_factor": 0.033,
"mover": 0
}
]'
python (example with pre-defined id-location)
import requests
url = "https://solar.alitiq.com/pv_systems/add"
payload = [
{
"location_id": 12,
"site_name": "test_2",
"latitude": 48.9,
"longitude": 10.3,
"power": 320,
"inverter_power": 300,
"azimuth": 180,
"tilt": 13,
"temp_factor": 0.033,
"mover": 0
},
{
"location_id": 12,
"site_name": "test_2",
"latitude": 48.9,
"longitude": 10.3,
"power": 320,
"inverter_power": 300,
"azimuth": 180,
"tilt": 15,
"temp_factor": 0.033,
"mover": 0
}
]
headers = {"Content-Type": "application/json", "x-api-key": {api-key}}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Delete
To delete a PV-System from you portfolio, you simply call another POST command:
POST: https://solar.alitiq.com/pv_systems/delete Show archive.org snapshot
Provide the location_id
to delete within the query of your request.
Example
cURL
curl --request POST \
--url 'https://solar.alitiq.com/pv_systems/delete?location_id=123' \
--header 'x-api-key: api-key'
python
import requests
url = "https://solar.alitiq.com/pv_systems/delete?location_id=123"
querystring = {"response_format":"html"}
payload = ""
headers = {"x-api-key": {api-key}}
response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
print(response.text)
For more examples, please ask our support team or use the Open-API doc in combination with Postman Show archive.org snapshot or insomnia Show archive.org snapshot .
List
GET: https://solar.alitiq.com/pv_systems/list Show archive.org snapshot
To inspect your portfolio of pv systems you can use the list endpoint.
Parameter | Description | Type |
---|---|---|
response_format | Define the response type csv | html | json are allowed parameters | string |
Example
cURL:
curl --request GET \
--url 'https://solar.alitiq.com/pv_systems/list?response_format=json' \
--header 'x-api-key: api-key'
python
import requests
url = "https://solar.alitiq.com/pv_systems/list"
querystring = {"response_format":"html"}
payload = ""
headers = {"x-api-key": {api-key}}
response = requests.request("GET", url, data=payload, params=querystring, headers=headers)
print(response.text)
2. Push measurement data ☀️
For an optimized solar power forecast we need to know the AC power output of the system. You have the ability to define the value of your measure in W (watt), kW (kilowatt) or MW (Megawatt). It is not possible to overwrite measurements at the moment.
By design, alitiq will adapt the raw forecasts according to the measurements pushed via this endpoint to our database. This means, when you send wrong data to our API, we will send wrong forecasts back to you. Do not hesitate to reach out to us, in case you think there is something wrong. Our goal is to provide you with accurate forecst and not with 💩.
POST: https://solar.alitiq.com/measurements/add Show archive.org snapshot
The request body expects a List of PvMeasurementForm
. The python object looks like this:
class PvMeasurementForm(BaseModel):
"""PvSystems Form data to post new sub systems"""
location_id: str
dt: datetime
power: float
irradiance: float = -1.0
power_measure: str = 'kW' # W | kW | MW | kWh | Wh | MWh
timezone: str = 'UTC'
interval_in_minutes: int = 15 # required when window_boundary is begin or center and for Energy to power
window_boundary: str = 'end' # begin | center | end
Parameter description
Parameter | Description | Type |
---|---|---|
location_id | identifier to map measurements to | string |
dt | timestamp of measurement | string |
power | your pv system power output after the inverter (DC) | float |
power_measure | W, kW, MW, kWh, Wh, MWh, DEFAULT is kW. | string |
irradiance | Only in W/m² in horizontal plane is allowed. Otherwise set this to -1 or do not list in form object | float |
timezone | Default: UTC. List of available timezones here: timezones.csv | string |
interval_in_minutes | forecast granularity/interval in minutes, Default 15 | integer |
window_boundary | Where is the timestamp located according to the time window. | string |
Irradiance should be provided in horizontal plane (pyranometer or Sensor in horizontal plane). If not available set this value to -1 !. By default the maximum payload size is 10MB. For long timeseries we suggest to chunk the payload by 10000.
Example
cURL
curl --request POST \
--url https://solar.alitiq.com/measurement/add \
--header 'Content-Type: application/json' \
--header 'x-api-key: {api-key}' \
--data '[
{
"location_id": 2,
"dt": "2022-03-06T09:45:00.000",
"power": 201.0,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T10:00:00.000",
"power": 213.0,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T10:15:00.000",
"power": 242.0,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T10:30:00.000",
"power": 270.0,
"irradiance": 234.0,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T10:45:00.000",
"power": 320,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T11:00:00.000",
"power": 397,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
}
]'
python:
import requests
url = "https://solar.alitiq.com/measurement/add"
payload = [
{
"location_id": 2,
"dt": "2022-03-06T09:45:00.000",
"power": 201,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T10:00:00.000",
"power": 213,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T10:15:00.000",
"power": 242,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T10:30:00.000",
"power": 270,
"irradiance": 234,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T10:45:00.000",
"power": 320,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
},
{
"location_id": 2,
"dt": "2022-03-06T11:00:00.000",
"power": 397,
"irradiance": -1,
"interval_in_minutes": 15,
"timezone": "UTC",
"window_boundary": "end",
"power_measure": "kW"
}
]
headers = {"Content-Type": "application/json", "x-api-key": {api-key}}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Inspect pushed measurement data
You have the ability to check out your pushed data with the inspect
endpoint.
GET: https://solar.alitiq.com/measurement/inspect?response_format=html&start_date=2022-01-01T00%3A00%3A00&end_date=2024-01-01T00%3A00%3A00&location_id=123 Show archive.org snapshot
Parameter | Description | Typ |
---|---|---|
response_format | html, csv, json, CSV und JSON with Standard pandas.DataFrame outputs. | string |
location_id | identifier for a PV-System to retrieve measurements stored on alitiqs database | string |
start_date (optional) | If you want to see a specific period from the past , define a start_date (and end_date) | string |
Format: YYYY-MM-DDTHH:MM:SS | ||
python string format: %Y-%m-%dT%H:%M:%S | ||
example: 2022-03-06T10:00:00 | ||
DEFAULT: latest | ||
end_date (optional) | If you want to see a specific period from the past , define a end_date (and start_date) | string |
Format: YYYY-MM-DDTHH:MM:SS | ||
python string format: %Y-%m-%dT%H:%M:%S | ||
example: 2022-03-06T10:00:00 | ||
DEFAULT: latest |
3. Forecast 📈
To access the latest forecast for your PV Systems you have two options using the GET method:
GET: https://solar.alitiq.com/forecast/single?location_id=123 Show archive.org snapshot
GET: https://solar.alitiq.com/forecast/portfolio Show archive.org snapshot
Single
With the single endpoint in forecast you are able to choose between csv, json and html response. It is possible to choose different dt_calc (=time where the forecast was originally calculated or the numerical weather prediction started its run)
Parameter | Description | Typ |
---|---|---|
location_id | identifier of pv-system to retrieve forecast for | string |
dt_calc (optional) | If you want to see a specific forecast from the past , . , | string |
Format: YYYY-MM-DDTHH:MM:SS | ||
python string format: %Y-%m-%dT%H:%M:%S | ||
example: 2022-03-06T10:00:00 | ||
DEFAULT: latest | ||
response_format | html, csv, json, CSV and JSON are default pandas.DataFrame outputs. | string |
power_measure | W, kW, MW, kWh, Wh, MWh , DEFAULT is kW | string |
timezone | Default: UTC. List of available timezones here timezones.csv Show archive.org snapshot | string |
interval_in_minutes | measuring interval in minutes, Default 15 | integer |
weather_model | Actually supported: icon_eu , icon_d2 , harmonie_knmi and optimized |
string |
dwd_solar_nowcast is available for Germany and surrounding areas. |
||
window_boundary | Where is the timestamp located accoridng to the time window. | string |
begin / center / end are allowed parameters | ||
Default: end |
Example
cURL
curl --request GET \
--url 'https://solar.alitiq.com/forecast/single?location_id=123&response_format=html&weather_model=icon_eu&timezone=UTC&power_measure=kW&interval_in_minutes=15' \
--header 'x-api-key: api-key'
python
import requests
url = "https://solar.alitiq.com/forecast/single"
querystring = {"location_id":"123","response_format":"html","weather_model":"icon_eu","timezone":"UTC","power_measure":"kW","interval_in_minutes":"15"}
payload = ""
headers = {"x-api-key": "api-key"}
response = requests.request("GET", url, data=payload, headers=headers, params=querystring)
print(response.text)
Output-Example:
{
"columns": [
"power"
],
"index": [
"2023-06-07T06:00:00.000",
"2023-06-07T07:00:00.000",
"2023-06-07T08:00:00.000",
"2023-06-07T09:00:00.000",
"2023-06-07T10:00:00.000",
"2023-06-07T11:00:00.000",
"2023-06-07T12:00:00.000",
"2023-06-07T13:00:00.000",
"2023-06-07T14:00:00.000",
"2023-06-07T15:00:00.000",
"2023-06-07T16:00:00.000",
"2023-06-07T17:00:00.000",
"2023-06-07T18:00:00.000",
"2023-06-07T19:00:00.000",
"2023-06-07T20:00:00.000",
"2023-06-07T21:00:00.000",
"2023-06-07T22:00:00.000",
"2023-06-07T23:00:00.000",
"2023-06-08T00:00:00.000",
"2023-06-08T01:00:00.000",
"2023-06-08T02:00:00.000",
"2023-06-08T03:00:00.000",
"2023-06-08T04:00:00.000",
"2023-06-08T05:00:00.000",
"2023-06-08T06:00:00.000",
"2023-06-08T07:00:00.000",
"2023-06-08T08:00:00.000",
"2023-06-08T09:00:00.000",
"2023-06-08T10:00:00.000",
"2023-06-08T11:00:00.000",
"2023-06-08T12:00:00.000",
"2023-06-08T13:00:00.000",
"2023-06-08T14:00:00.000",
"2023-06-08T15:00:00.000",
"2023-06-08T16:00:00.000",
"2023-06-08T17:00:00.000",
"2023-06-08T18:00:00.000",
"2023-06-08T19:00:00.000",
"2023-06-08T20:00:00.000",
"2023-06-08T21:00:00.000",
"2023-06-08T22:00:00.000",
"2023-06-08T23:00:00.000",
"2023-06-09T00:00:00.000",
"2023-06-09T01:00:00.000",
"2023-06-09T02:00:00.000",
"2023-06-09T03:00:00.000",
"2023-06-09T04:00:00.000",
"2023-06-09T05:00:00.000",
"2023-06-09T06:00:00.000"
],
"data": [
[
0.0
],
[
0.0
],
[
1131.38
],
[
2616.95
],
[
3659.3
],
[
3687.81
],
[
3446.74
],
[
2193.71
],
[
2447.07
],
[
2290.17
],
[
1367.97
],
[
837.82
],
[
520.33
],
[
301.78
],
[
86.93
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
6.97
],
[
303.09
],
[
820.72
],
[
1677.12
],
[
2259.5
],
[
2620.0
],
[
3548.06
],
[
3586.91
],
[
1546.83
],
[
1535.84
],
[
3064.67
],
[
3261.39
],
[
1806.88
],
[
972.62
],
[
620.05
],
[
315.31
],
[
90.49
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
0.0
],
[
199.14
],
[
322.47
]
]
}
Portfolio
With the portfolio endpoint in forecast you are able to choose between csv, json response. It is possible to choose different dt_calc (=time where the forecast was originally calculated or the numerical weather prediction started its run). You will receive forecasts for all pv-systems in your portfolio. If you want you can add a portfolio sum column.
Parameter | Description | Typ |
---|---|---|
location_id | identifier of pv-system to retrieve forecast for | string |
dt_calc (optional) | If you want to see a specific forecast from the past , . , | string |
Format: YYYY-MM-DDTHH:MM:SS | ||
python string format: %Y-%m-%dT%H:%M:%S | ||
example: 2022-03-06T10:00:00 | ||
DEFAULT: latest | ||
response_format | html, csv, json, CSV and JSON are default pandas.DataFrame outputs. | string |
power_measure | W, kW, MW, kWh, Wh, MWh , DEFAULT is kW | string |
timezone | Default: UTC. List of available timezones here timezones.csv Show archive.org snapshot | string |
interval_in_minutes | measuring interval in minutes, Default 15 | integer |
weather_model | Actually supported: icon_eu , icon_d2 , harmonie_knmi and optimized |
string |
dwd_solar_nowcast is available for Germany and surrounding areas. |
||
window_boundary | Where is the timestamp located accoridng to the time window. | string |
begin / center / end are allowed parameters | ||
Default: end | ||
portfolio_sum_column | True | False, to add a column with the portfolio sum |
Example
cURL
curl --request GET \
--url 'https://solar.alitiq.com/forecast/portfolio?response_format=html&weather_model=icon_eu&timezone=UTC&power_measure=kW&interval_in_minutes=15' \
--header 'x-api-key: api-key'
python
import requests
url = "https://solar.alitiq.com/forecast/portfolio"
querystring = {"response_format":"html","weather_model":"icon_eu","timezone":"UTC","power_measure":"kW","interval_in_minutes":"15", "portfolio_sum_column":"False"}
payload = ""
headers = {"x-api-key": "api-key"}
response = requests.request("GET", url, data=payload, headers=headers, params=querystring)
print(response.text)
Check available runs:
You have the ability to check for the availability of the 10 most recent runs using the
https://solar.alitiq.com/forecast/check/ Show archive.org snapshot Endpoint.
Parameter | Description | Type |
---|---|---|
location_id | Identifier to map measurements to | integer |
dt | Timestamp of measurement | string |
power | Your PV system power output after the inverter (DC) | float |
power_measure | Unit of power measurement (W, kW, MW, kWh, Wh, MWh) | string |
irradiance | Solar irradiance in W/m² (horizontal plane only) | float |
timezone | Timezone (default: UTC) | string |
interval_in_minutes | Forecast granularity/interval in minutes (default: 15) | integer |
window_boundary | Location of timestamp within the time window | string |
cURL
curl --request GET \
--url 'https://solar.alitiq.com/forecast/check?weather_model=icon_eu&location_id=1&number_of_runs=10' \
--header 'x-api-key: api-key'
python
import requests
url = "https://solar.alitiq.com/forecast/check"
querystring = {"weather_model":"icon_eu", "location_id": "1", "number_of_runs": 10}
payload = ""
headers = {"x-api-key": "api-key"}
response = requests.request("GET", url, data=payload, headers=headers, params=querystring)
print(response.text)
Output-Example for json:
{
"weather_model": "optimized",
"time": "2024-03-22T08:07:53.790794",
"dt_calcs": [
"2024-03-22T07:30:00",
"2024-03-22T07:15:00",
"2024-03-22T07:00:00",
"2024-03-22T06:45:00",
"2024-03-22T06:30:00",
"2024-03-22T06:15:00",
"2024-03-22T06:00:00",
"2024-03-21T17:00:00",
"2024-03-21T16:45:00",
"2024-03-21T16:30:00"
],
"location_id": [
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1"
]
}
Note: In case you receive the runs for the whole portfolio number_of_runs is just the number of rows that will be returned from the API.
🏗️ Next-to-Come
- Parameter validation
- Evaluation Endpoint
- Self consumption
- Timeshift detector
- Custom CSV files by passing config parameteres