☀️ alitiq-Solar-API ☀️

Updated . Posted . Visible to the public.

Welcome to the alitiq-Solar-API. The interface to manage and handle solar power forecast for your individual portfolio

Logo-1.png

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.

azimuth_tilt.png

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
Last edit
Daniel
Keywords
api, documentation, solar, api, forecast
Posted by Daniel to alitiq Knowledge (2024-06-12 18:08)