Quickstart
The Skyfora API gives you Global Navigation Satellite System (GNSS) measurement data and reference station metadata. Use it in your own applications and workflows.
This guide creates an API key, finds your stations, reads their latest values, and loads a time series into pandas. Responses are JSON.
1. Create an API key
Sign in to the Skyfora Portal and create an API key under your organization settings. The key is scoped to your organization and grants access to the stations and networks you are entitled to.
Include the key in every API request:
X-API-Key: your-api-key-here
2. Find your stations
Every measurement request needs station ids. Get them from Stations:
curl "https://api.skyfora.com/api/v1/stations?country_code=DE" \
-H "X-API-Key: your-api-key-here"
{
"stations": [
{
"id": "4f9b1c2e-6a70-4a3e-9a4f-2d8f5b7c0e11",
"display_name": "BERG001",
"resolution_seconds": 30,
"country_code": "DE",
"latitude": 50.94,
"longitude": 6.96
}
],
"pagination": { "page": 1, "page_size": 20, "total_items": 1, "total_pages": 1 }
}
id is the value the measurement endpoints take. resolution_seconds is the station's observation interval. You can also filter by network, bounding box, or name.
3. Get the latest values
Nearest Time returns one observation per station. Without time, it is each station's latest observation:
curl "https://api.skyfora.com/api/v1/measurements/nearest?station_ids=4f9b1c2e-6a70-4a3e-9a4f-2d8f5b7c0e11&data_vars=ztd,pwv" \
-H "X-API-Key: your-api-key-here"
{
"time": "2026-03-20T12:00:10Z",
"data": [
{
"timestamp": "2026-03-20T11:59:30.000Z",
"station_id": "4f9b1c2e-6a70-4a3e-9a4f-2d8f5b7c0e11",
"display_name": "BERG001",
"ztd": 2353.5,
"pwv": 12.3
}
],
"count": 1,
"missing_station_ids": []
}
Add time to get the observation nearest to another moment, for example time=2026-03-01T06:00:00Z.
4. Get a time series
Time Series returns every observation in a time range:
curl -X POST https://api.skyfora.com/api/v1/measurements/query \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key-here" \
-d '{
"start_time": "2026-03-20T00:00:00Z",
"end_time": "2026-03-21T00:00:00Z",
"station_ids": ["4f9b1c2e-6a70-4a3e-9a4f-2d8f5b7c0e11"],
"data_vars": ["ztd", "ztd_sigma", "pwv"]
}'
{
"data": [
{
"timestamp": "2026-03-20T00:00:00.000Z",
"station_id": "4f9b1c2e-6a70-4a3e-9a4f-2d8f5b7c0e11",
"display_name": "BERG001",
"ztd": 2353.5,
"ztd_sigma": 4.0,
"pwv": 12.3
}
],
"count": 1
}
For weeks or months of data, add "interval_seconds": 900 to get one averaged row per station every 15 minutes.
5. Load into pandas
import pandas as pd
import requests
resp = requests.post(
"https://api.skyfora.com/api/v1/measurements/query",
headers={"X-API-Key": "your-api-key-here"},
json={
"start_time": "2026-03-01T00:00:00Z",
"end_time": "2026-03-08T00:00:00Z",
"station_ids": ["4f9b1c2e-6a70-4a3e-9a4f-2d8f5b7c0e11", "7c2d9e40-1b5f-4c8a-8d3e-6f0a9b4c2d55"],
"data_vars": ["ztd", "pwv"],
"interval_seconds": 900,
},
timeout=60,
)
resp.raise_for_status()
df = pd.DataFrame(resp.json()["data"])
df["timestamp"] = pd.to_datetime(df["timestamp"])
pwv = df.pivot(index="timestamp", columns="display_name", values="pwv")
print(pwv.head())
Good to know
- Quality filter. Responses contain only observations that pass the Skyfora quality checks. See Data checks and quality control.
- Access. You can read only stations in the networks your organization is entitled to. Other stations return
403 Forbidden. - Request size. A time series request is limited in data points: the epochs in the range, summed over the stations. A request over your organization's limit returns
413 Content Too Large. See Data points. - Variables. Units, value formats, and how PWV is derived are in Variables.
- Errors. Every status code and what to do about it is in Errors.
Insight dashboard
The Skyfora Insight dashboard plots the same variables as the API, with the same default quality filter. Your organization needs access to the matching parameters.