This document describes how to authenticate and use the SkyTrackPro API for login, IGC upload, live tracking, and task access.
https://skytrackpro.ch/api/v1/...GET /api/v1/auth/me, POST /api/v1/flights/upload, etc.
The SkyTrackPro API allows trusted clients (mobile apps, companion tools, integrations) to:
Every API call requires:
X-Api-Key header or ?api_key=... query parameter)
Authorization: Bearer ...) or an existing
JScms session (browser).
Each external application is identified by an entry in
jscms_skytrack_api_clients. An API key is a 64-character string
stored in the api_key column and must be sent with
every request.
GET /api/v1/auth/me HTTP/1.1
Host: skytrackpro.ch
X-Api-Key: <YOUR_CLIENT_API_KEY>
Authorization: Bearer <USER_ACCESS_TOKEN>
GET /api/v1/auth/me?api_key=<YOUR_CLIENT_API_KEY> HTTP/1.1
Host: skytrackpro.ch
Authorization: Bearer <USER_ACCESS_TOKEN>
401 Unauthorized and
{ "ok": false, "message": "Missing/Invalid API key" }.
User authentication uses the existing JScms login system and issues opaque access tokens (short-lived) and refresh tokens (long-lived) for API calls. There are two ways to be "logged in":
/api/v1/auth/login or /api/v1/auth/refreshPOST /api/v1/auth/login
Endpoint: https://skytrackpro.ch/api/v1/auth/login
Request body (JSON):
{
"email": "pilot@example.com",
"password": "secret-password",
"remember": true
}
Example curl:
curl -X POST \
-H "Content-Type: application/json" \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
-d '{"email":"pilot@example.com","password":"secret","remember":true}' \
"https://skytrackpro.ch/api/v1/auth/login"
Successful response:
{
"ok": true,
"token": "64-char-hex-access-token",
"refresh_token": "64-char-hex-refresh-token",
"user": {
"id": 123,
"email": "pilot@example.com"
}
}
token (access token) in the
Authorization: Bearer ... header for all
user-level endpoints (flights upload, live start/stop/tick, etc.).
Store the refresh_token securely on the device and
use it to obtain new access tokens via
POST /api/v1/auth/refresh.
GET /api/v1/auth/me
Endpoint: https://skytrackpro.ch/api/v1/auth/me
Example:
curl \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
-H "Authorization: Bearer <USER_ACCESS_TOKEN>" \
"https://skytrackpro.ch/api/v1/auth/me"
Sample response:
{
"ok": true,
"user": {
"id": 123,
"email": "pilot@example.com",
"name": "Pilot Name",
"usergroupid": 5,
"access": 1,
"public": 1
}
}
POST /api/v1/auth/refresh
Endpoint: https://skytrackpro.ch/api/v1/auth/refresh
Use this endpoint when the access token has expired. The user does not need to re-enter their email and password, as long as the refresh token is still valid.
Request body (JSON):
{
"refresh_token": "64-char-hex-refresh-token"
}
Example curl:
curl -X POST \
-H "Content-Type: application/json" \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
-d '{"refresh_token":"64-char-hex-refresh-token"}' \
"https://skytrackpro.ch/api/v1/auth/refresh"
Successful response:
{
"ok": true,
"token": "new-64-char-hex-access-token",
"refresh_token": "64-char-hex-refresh-token",
"user": {
"id": 123,
"email": "pilot@example.com",
"name": "Pilot Name",
"usergroupid": 5,
"access": 1,
"public": 1
}
}
token (access) and refresh_token.401 due to an expired access token,
call /api/v1/auth/refresh with the refresh token.Upload an IGC file, analyze it, and create a SkyTrack flight entry. The user must have permission to manage tracks.
canManageTracks()agree/st_agree = 1)POST /api/v1/flights/upload
Endpoint: https://skytrackpro.ch/api/v1/flights/upload
Form fields:
file – IGC file (required)title – optional titleis_public – 0/1 (fallback for visibility)visibility – private|org|public|unlistedorg_id – optional organization idst_agree / agree – must be 1curl -X POST \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
-H "Authorization: Bearer <USER_ACCESS_TOKEN>" \
-F "file=@/path/to/flight.igc" \
-F "title=Evening soaring flight" \
-F "visibility=public" \
-F "st_agree=1" \
"https://skytrackpro.ch/api/v1/flights/upload"
JSON body:
{
"file_base64": "<base64 of IGC>",
"file_name": "flight.igc",
"title": "XC Flight",
"visibility": "public",
"org_id": 5,
"agree": 1
}
{
"ok": true,
"message": "IGC uploaded and analyzed.",
"track_id": 987,
"duplicate": false,
"date": "2025-06-13",
"year": 2025,
"visibility": "public",
"late_upload": false,
"notices": [],
"meta": {
"...": "full analysis / stats / compliance data"
}
}
Live tracking uses a separate database and two main tables:
jscms_skytrack_live_sessions and
jscms_skytrack_live_points. The API separates
pilot-side actions (start/stop/tick) from
viewer-side actions (sessions/users/track/tail).
Body:
{
"task_id": 123, // optional
"org_id": 5, // optional
"mode": "freeflight", // e.g. "freeflight", "task"
"device_label": "Phone"
}
Example:
curl -X POST \
-H "Content-Type: application/json" \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
-H "Authorization: Bearer <USER_ACCESS_TOKEN>" \
-d '{"task_id":123,"mode":"freeflight","device_label":"Phone"}' \
"https://skytrackpro.ch/api/v1/live/start"
Response:
{
"ok": true,
"session_id": 456
}
Body:
{
"session_id": 456
}
Example:
curl -X POST \
-H "Content-Type: application/json" \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
-H "Authorization: Bearer <USER_ACCESS_TOKEN>" \
-d '{"session_id":456}' \
"https://skytrackpro.ch/api/v1/live/stop"
Body:
{
"session_id": 456,
"points": [
{
"ts": 1730784300,
"lat": 46.123456,
"lon": 7.123456,
"alt": 1500,
"alt_bar": 1490,
"speed": 11.2,
"climb": 0.8,
"heading": 230
}
]
}
Example:
curl -X POST \
-H "Content-Type: application/json" \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
-H "Authorization: Bearer <USER_ACCESS_TOKEN>" \
-d '{"session_id":456,"points":[{"ts":1730784300,"lat":46.1,"lon":7.1,"alt":1500}]}' \
"https://skytrackpro.ch/api/v1/live/tick"
Response:
{
"ok": true,
"stored": 1
}
Query parameters:
org_id – optionaltask_id – optionalcurl \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
"https://skytrackpro.ch/api/v1/live/sessions?org_id=5"
Response includes a list of active sessions (no points).
Query parameters:
limit – default 500, max 5000since_ts – optional, only points after this UNIX tscurl \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
"https://skytrackpro.ch/api/v1/live/session/456/track?limit=500"
Response contains ordered points ready for plotting on a map.
Retrieve only the most recent point of the session.
curl \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
"https://skytrackpro.ch/api/v1/live/session/456/tail"
Perfect for ultra-light marker updates on the live map.
Query parameters:
org_id – optionaltask_id – optionalmode – optional (e.g. freeflight)since_ts – optional, filter for recent pointspublic_only – 0|1, hide non-public users if 1limit – default 200, max 1000 sessionscurl \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
"https://skytrackpro.ch/api/v1/live/users?public_only=1"
Response: markers[] with session, last point, and
basic user info – ideal for a live radar / map overview.
GET /api/v1/tasks
Endpoint: https://skytrackpro.ch/api/v1/tasks
Query parameters:
org_id – filter by organizationcategory_id – filter by categorypublished – 0 or 1curl \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
"https://skytrackpro.ch/api/v1/tasks?org_id=5&published=1"
GET /api/v1/tasks/{id}
Endpoint: https://skytrackpro.ch/api/v1/tasks/123
Returns full task metadata, including current version, distances,
and the parsed spec and calc JSON
for turnpoints and geometry.
curl \
-H "X-Api-Key: <YOUR_CLIENT_API_KEY>" \
"https://skytrackpro.ch/api/v1/tasks/123"
Typical flow for a SkyTrackPro client app that talks to the API:
api_key. Your app must send this key with every request via the X-Api-Key header.
POST /api/v1/auth/login with the pilot’s
email and password. Store the returned:
token – short-lived access tokenrefresh_token – long-lived refresh tokenX-Api-Key: <YOUR_CLIENT_API_KEY>Authorization: Bearer <ACCESS_TOKEN>401 due to an expired token:
POST /api/v1/auth/refresh with refresh_token.token with the new value./auth/login.
token and refresh_token and send no more
authenticated requests until they log in again.
// 1) Login
POST /api/v1/auth/login
{ email, password } → { token, refresh_token }
// 2) Store tokens securely
accessToken = token
refreshToken = refresh_token
// 3) Call protected endpoint
GET /api/v1/auth/me
Headers:
X-Api-Key: <client key>
Authorization: Bearer <accessToken>
// 4) On 401 due to expiry:
POST /api/v1/auth/refresh
{ refresh_token: refreshToken } → { token: newAccessToken }
accessToken = newAccessToken
retry original request
Need more endpoints or custom integrations? Contact the SkyTrackPro administrator to register a new API client and discuss your use case.