API Access

This guide demonstrates how to access Jua's weather forecasts through our REST API.

For information on when to use the API vs. File access, please refer to the Forecast README.

Setting up Authentication

All API requests require authentication using the X-API-Key header in the format {API_KEY_ID}:{API_SECRET}. Here's how to set it up:

API_KEY_ID = os.environ["JUA_API_KEY_ID"]
API_SECRET = os.environ["JUA_API_SECRET"]
AUTH_HEADER = {"X-API-Key": f"{API_KEY_ID}:{API_SECRET}"}

The examples below assume you have already set up the AUTH_HEADER as shown above.

Check forecast availability and timing

To check which forecast hours are currently available, use this API endpoint:

requests.get("https://api.jua.ai/v1/forecasting/ept1_5/forecasts/latest", headers=AUTH_HEADER).json()

Which will return the following fields:

  • forecast_url: A link to the specific forecast.

  • model_id: The model that was used to generate the forecast.

  • init_time: The initial conditions timestamp.

  • available_forecasted_hours: The number of hours, after the init_time, that have been forecasted.

  • available_variables: The available variables for this forecast.

Forecast Data

Single Point Request

Our REST API gives access to the forecast at a single point:

requests.get("https://api.jua.ai/v1/forecasting/ept1_5/forecasts/latest/47.38,8.52", headers=AUTH_HEADER).json()

For more information about available models and endpoints, please see our Release Notes.

By default, this request will return all available variables and only the first 24 hours of the forecast. Here is an example of requesting a single variable for a longer time range:

requests.get("https://api.jua.ai/v1/forecasting/ept1_5/forecasts/latest/47.38,8.52?variables=air_temperature_2m&max_lead_time=48", headers=AUTH_HEADER).json()

Multiple Points Request

If you're interested in more than one location, use the POST endpoint to retrieve up to 25 locations in a single request:

response = requests.post(
    "https://api.jua.ai/v1/forecasting/ept1_5/forecasts/latest",
    json={
        "min_lead_time": 48,
        "max_lead_time": 96,
        "points": [
            {"lat": 48.857, "lon": 2.352},  # Paris
            {"lat": 52.520, "lon": 3.405},  # Amsterdam
            {"lat": 40.417, "lon": -3.703}, # Madrid
        ],
        "variables": [
            "air_temperature_at_height_level_2m",
            "wind_speed_at_height_level_100m"
        ]
    },
    headers=AUTH_HEADER
)

Response Notes

  • The server returns the nearest available points to what have been requested. For example, if you request (48.857, 2.352), it will return the values at (48.829, 2.351). The returned_latlon field lists the actual returned locations.

  • If you request more hours than what is currently available from the latest forecast (because the forecast is currently disseminating), then the response will contain all of the available data only.

  • The variables and units are documented in:

Real-World Example

Get 100m wind speed at 4 locations in Germany

import os
import requests
import matplotlib.pyplot as plt
import pandas as pd
from datetime import datetime, timezone

# Authentication
API_KEY_ID = os.environ["JUA_API_KEY_ID"]
API_SECRET = os.environ["JUA_API_SECRET"]
AUTH_HEADER = {"X-API-Key": f"{API_KEY_ID}:{API_SECRET}"}

VARIABLES = ["wind_speed_at_height_level_100m"]
LOCATIONS= [
    {"name": "Berlin", "lat": 52.52, "lon": 13.41},
    {"name": "Hamburg", "lat": 53.55, "lon": 10.00},
    {"name": "Munich", "lat": 48.14, "lon": 11.58},
    {"name": "Frankfurt", "lat": 50.11, "lon": 8.68}
]

# Request data for 4 German cities
response = requests.post(
    "https://api.jua.ai/v1/forecasting/ept1_5/forecasts/latest",
    json={
        "min_lead_time": 0,
        "max_lead_time": 120,
        "points": LOCATIONS,
        "variables": VARIABLES
    },
    headers=AUTH_HEADER
)

data = response.json()['forecast']

# Create DataFrames for plotting
dfs = {}
init_time = datetime.fromisoformat(data["init_time"].replace("Z", "+00:00"))

# Process each location
for i, point in enumerate(data["points"]):
        # match location to city
        city_name = LOCATIONS[i]["name"]
        values = point[VARIABLES].indexOf
        timestamps = [init_time.replace(tzinfo=timezone.utc) + pd.Timedelta(hours=h) for h in range(len(values))]
        
        # Create DataFrame
        dfs[city_name] = pd.DataFrame({
            'timestamp': timestamps,
            'wind_speed': values
        })

# Plot the data
plt.figure(figsize=(12, 6))
for city, df in dfs.items():
    plt.plot(df['timestamp'], df['wind_speed'], label=city)

plt.title(f'100m Wind Speed Forecast - Init: {init_time.strftime("%Y-%m-%d %H:%M")} UTC')
plt.xlabel('Time (UTC)')
plt.ylabel('Wind Speed (m/s)')
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.savefig('wind_forecast.png')
plt.show()

Last updated