Menu
Back to Documentation Index

API Documentation

Complete API guide with examples and integration patterns

VATSWIM API Documentation

Version: 1.1.0

Last Updated: January 27, 2026

Status: Production Ready

API Base URL: https://perti.vatcscc.org/api/swim/v1

WebSocket URL: wss://perti.vatcscc.org/api/swim/v1/ws


> FIXM Migration Complete (2026-01-27)

>

> The VATSWIM API now uses FIXM-aligned field naming exclusively. Legacy OOOI column names have been replaced:

>

> | Legacy Name (Removed) | FIXM-Aligned Name (Current) |

> | --------------------- | --------------------------- |

> | out_utc | actual_off_block_time |

> | off_utc | actual_time_of_departure |

> | on_utc | actual_landing_time |

> | in_utc | actual_in_block_time |

> | eta_utc | estimated_time_of_arrival |

> | etd_utc | estimated_off_block_time |

>

> After FIXM cutover:

>

> - SWIM database uses FIXM column names only

> - API responses use FIXM field names exclusively

> - ADL database retains legacy column names (source of truth)

> - Ingest endpoints accept both legacy and FIXM input names for compatibility

>

> See VATSWIM_FIXM_Field_Mapping.md for complete mapping.


Table of Contents

1. Overview

2. Authentication

3. REST API Endpoints

4. WebSocket Real-Time API

5. Data Models

6. Python SDK

7. Configuration Reference

8. Database Schema

9. Deployment & Operations

10. Implementation Status


1. Overview

1.1 What is VATSWIM?

VATSWIM (System Wide Information Management) is a comprehensive API that provides access to real-time and historical flight data from the VATSIM virtual air traffic control network. The API follows FAA SWIM and FIXM (Flight Information Exchange Model) standards to provide standardized flight data to external consumers.

1.2 Key Features

  • REST API for querying flight data, positions, and traffic management initiatives (TMIs)
  • WebSocket API for real-time event streaming (departures, arrivals, position updates)
  • FIXM-aligned field naming with optional legacy format support
  • GeoJSON output for position data
  • Tiered access control with API key authentication
  • Python SDK for easy client integration
  • 1.3 Architecture Overview

    ┌─────────────────┐      ┌─────────────────┐      ┌─────────────────┐
    │  VATSIM Network │─────▶│   ADL Daemon    │─────▶│   SWIM_API DB   │
    │   (live data)   │      │  (15s refresh)  │      │  (Azure SQL)    │
    └─────────────────┘      └────────┬────────┘      └────────┬────────┘
                                      │                        │
                                      │ events                 │ queries
                                      ▼                        ▼
                             ┌─────────────────┐      ┌─────────────────┐
                             │   WebSocket     │      │    REST API     │
                             │    Server       │      │   Endpoints     │
                             └────────┬────────┘      └────────┬────────┘
                                      │                        │
                        ┌─────────────┴────────────────────────┴─────────────┐
                        │                  SWIM Clients                       │
                        │  (vNAS, CRC, SimAware, Virtual Airlines, etc.)     │
                        └─────────────────────────────────────────────────────┘
    

    1.4 Cost Structure

    ComponentMonthly Cost
    SWIM_API Database (Azure SQL Basic)$5
    WebSocket Server (self-hosted)$0
    Total$5/month

    2. Authentication

    2.1 API Keys

    All API requests require authentication via Bearer token or query parameter.

    Header Authentication (Recommended):

    Authorization: Bearer swim_dev_your_key_here
    

    Query Parameter (WebSocket):

    wss://perti.vatcscc.org/api/swim/v1/ws?api_key=swim_dev_your_key_here
    

    2.2 API Key Tiers

    TierPrefixRate LimitMax WS ConnectionsWrite Access
    systemswim_sys_30,000/min10,000Yes
    partnerswim_par_3,000/min500Limited
    developerswim_dev_300/min50No
    publicswim_pub_100/min5No

    2.3 Creating API Keys

    API keys are stored in the dbo.swim_api_keys table in VATSIM_ADL database.

    INSERT INTO dbo.swim_api_keys (api_key, tier, owner_name, owner_email, description)
    VALUES (
        'swim_dev_' + LOWER(CONVERT(VARCHAR(36), NEWID())),
        'developer',
        'Developer Name',
        'email@example.com',
        'API key for development testing'
    );
    

    2.4 Key Validation

    The system validates keys against the database with a 5-minute cache TTL:

  • Checks is_active = 1
  • Checks expires_at is null or in the future
  • Updates last_used_at on successful authentication

  • 3. REST API Endpoints

    3.1 API Index

    Endpoint: GET /api/swim/v1

    Returns API information and available endpoints.

    Response:

    {
      "success": true,
      "data": {
        "name": "VATSWIM API",
        "version": "1.0.0",
        "description": "System Wide Information Management for VATSIM",
        "documentation": "https://perti.vatcscc.org/docs/swim/",
        "endpoints": {
          "flights": {
            "GET /api/swim/v1/flights": "List flights with filters",
            "GET /api/swim/v1/flight": "Get single flight by GUFI or flight_key"
          },
          "positions": {
            "GET /api/swim/v1/positions": "Bulk flight positions (GeoJSON)"
          },
          "tmi": {
            "GET /api/swim/v1/tmi/programs": "Active TMI programs (GS/GDP)",
            "GET /api/swim/v1/tmi/controlled": "Flights under TMI control"
          }
        }
      }
    }
    

    3.2 Flights List

    Endpoint: GET /api/swim/v1/flights

    Returns paginated list of flights with optional filtering.

    Query Parameters:

    ParameterTypeDescription
    statusstringactive (default), completed, or all
    dept_icaostringComma-separated departure airports (e.g., KJFK,KLGA)
    dest_icaostringComma-separated destination airports
    artccstringComma-separated ARTCCs (e.g., ZNY,ZBW)
    callsignstringCallsign pattern with wildcards (e.g., UAL)
    tmi_controlledbooleantrue to filter TMI-controlled flights
    phasestringFlight phase filter (e.g., ENROUTE,DESCENDING)
    formatstringResponse format (see below)
    pageintPage number (default: 1)
    per_pageintResults per page (default: 100, max: 1000)
    Supported Formats:

    FormatContent-TypeDescription
    jsonapplication/jsonStandard JSON with snake_case fields (default)
    fixmapplication/jsonJSON with FIXM 4.3.0 camelCase field names
    xmlapplication/xmlXML format for enterprise/SOAP integrations
    geojsonapplication/geo+jsonGeoJSON FeatureCollection for mapping (Leaflet, Mapbox)
    csvtext/csvCSV for spreadsheet/analytics export
    kmlapplication/vnd.google-earth.kml+xmlKML for Google Earth visualization
    ndjsonapplication/x-ndjsonNewline-delimited JSON for streaming/bulk processing
    Example Request:

    curl -H "Authorization: Bearer swim_dev_test" \
      "https://perti.vatcscc.org/api/swim/v1/flights?dest_icao=KJFK&status=active"
    

    Response (Legacy Format):

    {
      "success": true,
      "data": [
        {
          "gufi": "VAT-20260116-UAL123-KLAX-KJFK",
          "flight_uid": 12345,
          "flight_key": "UAL123_KLAX_KJFK_20260116",
          "identity": {
            "callsign": "UAL123",
            "cid": 1234567,
            "aircraft_type": "B738",
            "aircraft_icao": "B738",
            "weight_class": "L",
            "wake_category": "M",
            "airline_icao": "UAL",
            "airline_name": "United Airlines"
          },
          "flight_plan": {
            "departure": "KLAX",
            "destination": "KJFK",
            "alternate": "KEWR",
            "cruise_altitude": 35000,
            "cruise_speed": 450,
            "route": "DOTSS5 KAYOH J146 ABQ J80 HVE J100 STL J24 JHW LENDY5",
            "flight_rules": "I",
            "departure_artcc": "ZLA",
            "destination_artcc": "ZNY",
            "arrival_fix": "LENDY",
            "arrival_procedure": "LENDY5"
          },
          "position": {
            "latitude": 40.1234,
            "longitude": -74.5678,
            "altitude_ft": 35000,
            "heading": 85,
            "ground_speed_kts": 480,
            "vertical_rate_fpm": 0,
            "current_artcc": "ZNY"
          },
          "progress": {
            "phase": "ENROUTE",
            "is_active": true,
            "distance_remaining_nm": 125.4,
            "pct_complete": 95.2,
            "time_to_dest_min": 15.7
          },
          "times": {
            "eta": "2026-01-16T18:45:00Z",
            "eta_runway": "2026-01-16T18:52:00Z",
            "out": "2026-01-16T14:05:00Z",
            "off": "2026-01-16T14:18:00Z"
          },
          "tmi": {
            "is_controlled": false,
            "ground_stop_held": false
          }
        }
      ],
      "pagination": {
        "total": 156,
        "page": 1,
        "per_page": 100,
        "total_pages": 2,
        "has_more": true
      },
      "timestamp": "2026-01-16T18:30:00Z"
    }
    

    3.3 Single Flight

    Endpoint: GET /api/swim/v1/flight

    Returns a single flight by GUFI or flight_key.

    Query Parameters:

    ParameterTypeDescription
    gufistringGlobally Unique Flight Identifier
    flight_keystringADL flight key
    formatstringlegacy or fixm

    3.4 Positions (GeoJSON)

    Endpoint: GET /api/swim/v1/positions

    Returns bulk flight positions in GeoJSON FeatureCollection format.

    Query Parameters:

    ParameterTypeDescription
    dept_icaostringDeparture airport filter
    dest_icaostringDestination airport filter
    artccstringARTCC filter
    boundsstringBounding box: minLon,minLat,maxLon,maxLat
    tmi_controlledbooleanTMI-controlled flights only
    phasestringFlight phase filter
    include_routebooleanInclude route string in properties
    Example Response:

    {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          "id": 12345,
          "geometry": {
            "type": "Point",
            "coordinates": [-74.5678, 40.1234, 35000]
          },
          "properties": {
            "flight_uid": 12345,
            "callsign": "UAL123",
            "aircraft": "B738",
            "departure": "KLAX",
            "destination": "KJFK",
            "phase": "ENROUTE",
            "altitude": 35000,
            "heading": 85,
            "groundspeed": 480,
            "distance_remaining_nm": 125.4,
            "tmi_status": "none"
          }
        }
      ],
      "metadata": {
        "count": 2847,
        "timestamp": "2026-01-16T18:30:00Z",
        "source": "vatcscc"
      }
    }
    

    3.5 TMI Programs

    Endpoint: GET /api/swim/v1/tmi/programs

    Returns active Traffic Management Initiatives (Ground Stops, GDPs).

    Query Parameters:

    ParameterTypeDescription
    typestringall (default), gs, or gdp
    airportstringAirport ICAO filter
    artccstringARTCC filter
    include_historybooleanInclude recently ended programs
    Example Response:

    {
      "success": true,
      "data": {
        "ground_stops": [
          {
            "type": "ground_stop",
            "airport": "KJFK",
            "airport_name": "John F Kennedy Intl",
            "artcc": "ZNY",
            "reason": "Thunderstorms",
            "probability_of_extension": 60,
            "times": {
              "start": "2026-01-16T17:00:00Z",
              "end": "2026-01-16T19:00:00Z"
            },
            "is_active": true
          }
        ],
        "gdp_programs": [
          {
            "type": "gdp",
            "program_id": "GDP_KEWR_20260116",
            "airport": "KEWR",
            "airport_name": "Newark Liberty Intl",
            "artcc": "ZNY",
            "reason": "Volume",
            "rates": {"program_rate": 40},
            "delays": {
              "limit_minutes": 90,
              "average_minutes": 45,
              "maximum_minutes": 87
            },
            "flights": {
              "total": 156,
              "affected": 89
            },
            "is_active": true
          }
        ],
        "summary": {
          "active_ground_stops": 1,
          "active_gdp_programs": 1,
          "total_controlled_airports": 2
        }
      }
    }
    

    3.6 TMI Controlled Flights

    Endpoint: GET /api/swim/v1/tmi/controlled

    Returns flights currently under TMI control.

    3.7 ADL Flight Ingest

    Endpoint: POST /api/swim/v1/ingest/adl

    Receives flight data from authoritative sources. Requires write access (system or partner tier).

    Maximum batch size: 500 flights per request

    Request Body:

    {
      "flights": [
        {
          "callsign": "UAL123",
          "dept_icao": "KJFK",
          "dest_icao": "KLAX",
          "cid": 1234567,
          "aircraft_type": "B738",
          "route": "DCT JFK J584 ORD J64 LAX",
          "phase": "ENROUTE",
          "is_active": true,
          "latitude": 40.1234,
          "longitude": -74.5678,
          "altitude_ft": 35000,
          "heading_deg": 270,
          "groundspeed_kts": 450,
          "vertical_rate_fpm": -500,
          "out_utc": "2026-01-16T14:05:00Z",
          "off_utc": "2026-01-16T14:18:00Z",
          "eta_utc": "2026-01-16T18:45:00Z",
          "tmi": {
            "ctl_type": "GDP",
            "slot_time_utc": "2026-01-16T18:30:00Z",
            "delay_minutes": 45
          }
        }
      ]
    }
    

    Response:

    {
      "success": true,
      "data": {
        "processed": 1,
        "created": 0,
        "updated": 1,
        "errors": 0,
        "error_details": []
      },
      "timestamp": "2026-01-16T12:00:00Z",
      "meta": {
        "source": "vatcscc",
        "batch_size": 1
      }
    }
    

    3.8 Track Position Ingest

    Endpoint: POST /api/swim/v1/ingest/track

    Receives real-time track/position updates from authoritative sources (vNAS, CRC, EuroScope, AOC systems).

    Maximum batch size: 1000 tracks per request (higher limit for frequent position updates)

    Request Body:

    {
      "tracks": [
        {
          "callsign": "UAL123",
          "latitude": 40.6413,
          "longitude": -73.7781,
          "altitude_ft": 35000,
          "ground_speed_kts": 450,
          "heading_deg": 270,
          "vertical_rate_fpm": -500,
          "squawk": "1200",
          "track_source": "radar"
        }
      ]
    }
    

    Track Fields:

    FieldTypeRequiredDescription
    callsignstringYesAircraft callsign
    latitudenumberYesLatitude (-90 to 90)
    longitudenumberYesLongitude (-180 to 180)
    altitude_ftintegerNoAltitude in feet MSL
    ground_speed_ktsintegerNoGround speed in knots
    heading_degintegerNoHeading (0-360)
    vertical_rate_fpmintegerNoVertical rate (+ = climb, - = descend)
    squawkstringNoTransponder code (4 digits)
    track_sourcestringNoradar, ads-b, mlat, mode-s, acars
    timestampdatetimeNoObservation time (ISO 8601)
    Response:

    {
      "success": true,
      "data": {
        "processed": 100,
        "updated": 95,
        "not_found": 5,
        "errors": 0,
        "error_details": []
      },
      "timestamp": "2026-01-16T12:00:00Z",
      "meta": {
        "source": "vnas",
        "batch_size": 100
      }
    }
    

    Notes:

  • Tracks are matched by callsign to existing active flights
  • Flights not found are skipped (not_found count) but not considered errors
  • Use this endpoint for high-frequency position updates from radar/ADS-B systems
  • 3.9 Metering Data

    Endpoint: GET /api/swim/v1/metering/{airport}

    Returns TBFM-style metering data for arrivals to an airport.

    Path Parameters:

    ParameterTypeDescription
    airportstringDestination airport ICAO code (e.g., KJFK)
    Query Parameters:

    ParameterTypeDescription
    statusstringFilter by metering status: UNMETERED, METERED, FROZEN, SUSPENDED, EXEMPT
    runwaystringFilter by arrival runway (e.g., 31L)
    streamstringFilter by arrival stream/corner post
    metered_onlybooleanOnly return flights with metering data (default: true)
    formatstringResponse format: json, fixm, xml, csv, ndjson
    Example Response:

    {
      "success": true,
      "data": {
        "airport": "KJFK",
        "type": "metering_data",
        "flights": [
          {
            "gufi": "VAT-20260116-UAL123-KORD-KJFK",
            "callsign": "UAL123",
            "sequence_number": 5,
            "scheduled_time_of_arrival": "2026-01-16T18:30:00Z",
            "metering_time": "2026-01-16T18:15:00Z",
            "metering_delay": 5,
            "metering_frozen": true,
            "metering_status": "METERED",
            "arrival_stream": "NORTH",
            "arr_runway": "31L"
          }
        ],
        "count": 15,
        "summary": {
          "total": 15,
          "metered": 12,
          "frozen": 3,
          "avg_delay_minutes": 4.2
        }
      }
    }
    

    Sequence Endpoint: GET /api/swim/v1/metering/{airport}/sequence

    Returns a compact arrival sequence list sorted by sequence number, optimized for datablock display.

    3.10 Metering Ingest

    Endpoint: POST /api/swim/v1/ingest/metering

    Receives TBFM-style metering data from authoritative sources (SimTraffic, vATCSCC).

    Maximum batch size: 500 metering records per request

    Request Body:

    {
      "airport": "KJFK",
      "metering_point": "CAMRN",
      "metering": [
        {
          "callsign": "UAL123",
          "sequence_number": 5,
          "scheduled_time_of_arrival": "2026-01-16T18:30:00Z",
          "metering_time": "2026-01-16T18:15:00Z",
          "metering_delay": 5,
          "metering_frozen": true,
          "arrival_stream": "NORTH",
          "arrival_runway": "31L",
          "metering_status": "METERED"
        }
      ]
    }
    

    Response:

    {
      "success": true,
      "data": {
        "processed": 10,
        "updated": 8,
        "not_found": 2,
        "errors": 0
      },
      "meta": {
        "source": "simtraffic",
        "airport": "KJFK",
        "metering_point": "CAMRN"
      }
    }
    

    3.11 TMI Reroutes

    Endpoint: GET /api/swim/v1/tmi/reroutes

    Returns reroute definitions for Traffic Management Initiatives.

    Query Parameters:

    ParameterTypeDescription
    statusstringFilter by status (comma-separated): 0=Draft, 1=Proposed, 2=Active, 3=Monitoring, 4=Expired, 5=Cancelled
    activestringIf 1, returns only active reroutes (status 1,2,3)
    limitintMaximum results (default: 100)
    offsetintPagination offset
    Example Response:

    {
      "status": "ok",
      "total": 5,
      "counts": {
        "Active": 2,
        "Proposed": 1,
        "Monitoring": 2
      },
      "reroutes": [
        {
          "id": 1,
          "status": 2,
          "status_label": "Active",
          "name": "KJFK_WX_REROUTE",
          "adv_number": "ADV-2026-001",
          "start_utc": "2026-01-16T14:00:00",
          "end_utc": "2026-01-16T20:00:00",
          "protected_fixes": "CAMRN,PARCH",
          "avoid_fixes": "LENDY",
          "dest_airports": "KJFK",
          "dest_centers": "ZNY"
        }
      ]
    }
    

    3.12 Unified TMI Measures

    Endpoint: GET /api/swim/v1/tmi/measures

    Returns ALL traffic management measures from both USA (vATCSCC) and external providers (ECFMP, NavCanada, VATPAC) in a unified TFMS/FIXM-aligned format.

    Query Parameters:

    ParameterTypeDescription
    providerstringFilter by provider: vATCSCC, ECFMP, etc. (comma-separated)
    typestringMeasure type: GS, GDP, AFP, MIT, MINIT, MDI, RATE, REROUTE
    airportstringControl element filter (comma-separated ICAO codes)
    sourcestringusa (vATCSCC only), external (non-USA), or all (default)
    active_onlybooleanFilter to active measures only (default: true)
    pageintPage number (default: 1)
    per_pageintResults per page (default: 100, max: 1000)
    Example Request:

    curl -H "Authorization: Bearer swim_dev_test" \
      "https://perti.vatcscc.org/api/swim/v1/tmi/measures?type=MIT,GS&active_only=true"
    

    Example Response:

    {
      "success": true,
      "data": {
        "measures": [
          {
            "id": "USA-45",
            "guid": "a1b2c3d4-...",
            "provider": {
              "code": "vATCSCC",
              "name": "VATSIM Command Center (USA)"
            },
            "ident": "GS_KJFK_45",
            "type": "GS",
            "value": null,
            "unit": null,
            "controlElement": "KJFK",
            "elementType": "APT",
            "reason": "Thunderstorms",
            "filters": {
              "arrivalAerodrome": ["KJFK"]
            },
            "timeRange": {
              "start": "2026-01-17T18:00:00Z",
              "end": "2026-01-17T20:00:00Z"
            },
            "status": "ACTIVE",
            "_source": "usa"
          },
          {
            "id": "ECFMP-456",
            "guid": "e5f6g7h8-...",
            "provider": {
              "code": "ECFMP",
              "name": "EUROCONTROL Flow Management"
            },
            "ident": "EGTT22A",
            "type": "MDI",
            "value": 120,
            "unit": "SEC",
            "reason": "CTP Event Traffic",
            "event": {
              "id": 123,
              "code": "CTP2026",
              "name": "Cross the Pond 2026"
            },
            "filters": {
              "departureAerodrome": ["KJFK", "KEWR"],
              "arrivalAerodrome": ["EGLL", "EGKK"]
            },
            "exemptions": {
              "eventFlights": true
            },
            "timeRange": {
              "start": "2026-03-15T12:00:00Z",
              "end": "2026-03-15T20:00:00Z"
            },
            "status": "ACTIVE",
            "_source": "external"
          }
        ],
        "statistics": {
          "by_provider": { "vATCSCC": 5, "ECFMP": 3 },
          "by_type": { "GS": 2, "MIT": 3, "MDI": 2, "GDP": 1 },
          "by_source": { "usa": 5, "external": 3 }
        },
        "pagination": {
          "total": 8,
          "page": 1,
          "per_page": 100
        }
      }
    }
    

    3.13 External Flow Management

    Provider-agnostic integration for external flow management systems. Supports ECFMP (Europe/NAT), NavCanada, VATPAC, and future regional providers.

    3.13.1 Flow Index

    Endpoint: GET /api/swim/v1/tmi/flow/

    Returns overview of external flow management endpoints and active counts.

    3.13.2 Flow Providers

    Endpoint: GET /api/swim/v1/tmi/flow/providers

    Returns registered external flow management providers.

    Query Parameters:

    ParameterTypeDescription
    providerstringFilter by provider code
    regionstringFilter by region: EUR, NAM, NAT, PAC
    active_onlybooleanFilter to active providers only (default: true)
    Example Response:

    {
      "success": true,
      "data": {
        "providers": [
          {
            "id": 1,
            "code": "ECFMP",
            "name": "EUROCONTROL Flow Management",
            "api": {
              "base_url": "https://ecfmp.vatsim.net/api/v1",
              "version": "v1"
            },
            "coverage": {
              "regions": ["EUR", "NAT"],
              "firs": ["EGTT", "EGPX", "CZQX"]
            },
            "sync": {
              "enabled": true,
              "interval_sec": 300,
              "last_sync_utc": "2026-01-17T15:30:00Z",
              "last_status": "SUCCESS"
            },
            "is_active": true
          }
        ]
      }
    }
    

    3.13.3 Flow Events

    Endpoint: GET /api/swim/v1/tmi/flow/events

    Returns special events (CTP, FNO, etc.) from external providers.

    Query Parameters:

    ParameterTypeDescription
    providerstringFilter by provider: ECFMP, NAVCAN, etc.
    codestringEvent code filter: CTP2026, FNO2026
    statusstringStatus filter: SCHEDULED, ACTIVE, COMPLETED
    include_participantsbooleanInclude participant list (default: false)
    Example Response:

    {
      "success": true,
      "data": {
        "events": [
          {
            "id": 123,
            "guid": "abc123...",
            "provider": { "code": "ECFMP", "name": "EUROCONTROL Flow Management" },
            "code": "CTP2026",
            "name": "Cross the Pond 2026",
            "type": "SPECIAL",
            "firs": ["EGTT", "EGPX", "CZQX", "KZNY"],
            "timeRange": {
              "start": "2026-03-15T12:00:00Z",
              "end": "2026-03-15T20:00:00Z"
            },
            "exemptions": {
              "groundStop": true,
              "gdpPriority": true
            },
            "status": "SCHEDULED",
            "participantCount": 1247
          }
        ]
      }
    }
    

    3.13.4 Flow Measures

    Endpoint: GET /api/swim/v1/tmi/flow/measures

    Returns flow measures (MIT, MINIT, MDI, etc.) from external providers only.

    Query Parameters:

    ParameterTypeDescription
    providerstringFilter by provider
    typestringMeasure type: MIT, MINIT, MDI, RATE, GS, REROUTE
    event_idintFilter by associated event
    airportstringFilter by control element
    active_onlybooleanFilter to active measures (default: true)
    Measure Types (TFMS-aligned):

    TypeDescriptionUnit
    MITMiles-In-TrailNM
    MINITMinutes-In-TrailMIN
    MDIMinimum Departure IntervalSEC
    RATEDeparture Rate CapPER_HOUR
    GDPGround Delay ProgramMIN
    AFPAirspace Flow ProgramMIN
    Example Response:

    {
      "success": true,
      "data": {
        "measures": [
          {
            "id": 456,
            "ident": "EGTT22A",
            "provider": { "code": "ECFMP" },
            "type": "MDI",
            "value": 120,
            "unit": "SEC",
            "event": { "id": 123, "code": "CTP2026" },
            "reason": "CTP Event Traffic",
            "filters": {
              "departureAerodrome": ["KJFK", "KEWR", "KLGA"],
              "arrivalAerodrome": ["EGLL", "EGKK"]
            },
            "exemptions": {
              "eventFlights": true
            },
            "mandatoryRoute": ["KJFK", "MERIT", "NAT-A", "EGLL"],
            "timeRange": {
              "start": "2026-03-15T12:00:00Z",
              "end": "2026-03-15T20:00:00Z"
            },
            "status": "ACTIVE"
          }
        ]
      }
    }
    

    3.14 JATOC Incidents

    Endpoint: GET /api/swim/v1/jatoc/incidents

    Returns JATOC (Joint Air Traffic Operations Center) incident records.

    Query Parameters:

    ParameterTypeDescription
    lifecycle_statusstringFilter: OPEN, IN_PROGRESS, RESOLVED, CLOSED
    facilitystringFilter by facility (partial match)
    facilitiesstringFilter by multiple facilities (comma-separated, exact match)
    facility_typestringFilter: ARTCC, TRACON, ATCT, FSS
    limitintResults per page (default: 50, max: 100)
    offsetintPagination offset
    Example Response:

    {
      "success": true,
      "data": [
        {
          "id": 1,
          "incident_number": "2026-001",
          "facility": "KJFK",
          "facility_type": "ATCT",
          "incident_type": "EQUIPMENT",
          "lifecycle_status": "RESOLVED",
          "severity": "MEDIUM",
          "summary": "Primary radar outage",
          "start_utc": "2026-01-16T14:00:00",
          "end_utc": "2026-01-16T15:30:00"
        }
      ],
      "pagination": {
        "total": 45,
        "limit": 50,
        "offset": 0,
        "page": 1
      }
    }
    

    3.13 Runway Configuration Presets

    Endpoint: GET /api/swim/v1/splits/presets

    Returns saved runway configuration presets.

    Query Parameters:

    ParameterTypeDescription
    artccstringFilter by ARTCC
    airportstringFilter by airport
    idintGet single preset by ID
    Example Response:

    {
      "success": true,
      "presets": [
        {
          "id": 1,
          "name": "KJFK_ILS31L_VIS31R",
          "artcc": "ZNY",
          "airport": "KJFK",
          "description": "ILS 31L arrivals, Visual 31R departures",
          "is_default": false,
          "positions": [
            {"runway": "31L", "operation": "ARR", "is_primary": true, "rate": 40},
            {"runway": "31R", "operation": "DEP", "is_primary": true, "rate": 45}
          ]
        }
      ]
    }
    


    4. WebSocket Real-Time API

    4.1 Connection

    Connect to the WebSocket server with your API key:

    const ws = new WebSocket('wss://perti.vatcscc.org/api/swim/v1/ws?api_key=YOUR_KEY');
    

    Connection Response:

    {
      "type": "connected",
      "data": {
        "client_id": "c_abc123def456",
        "server_time": "2026-01-16T18:30:00Z",
        "version": "1.0.0"
      }
    }
    

    4.2 Subscribing to Events

    Send a subscribe message to receive specific event types:

    {
      "action": "subscribe",
      "channels": ["flight.departed", "flight.arrived", "tmi.issued"],
      "filters": {
        "airports": ["KJFK", "KLGA", "KEWR"],
        "artccs": ["ZNY"]
      }
    }
    

    Available Channels:

    ChannelDescription
    flight.createdNew pilot connected to network
    flight.departedAircraft wheels-up (OFF time set)
    flight.arrivedAircraft wheels-down (IN time set)
    flight.deletedPilot disconnected
    flight.positionsBatched position updates
    flight.All flight events
    tmi.issuedNew Ground Stop/GDP created
    tmi.releasedTMI ended/released
    tmi.All TMI events
    system.heartbeatServer keepalive (30s interval)
    Subscription Filters:

    FilterTypeDescription
    airportsarrayICAO codes to filter by departure/destination
    artccsarrayARTCC IDs to filter
    callsign_prefixarrayCallsign prefixes (e.g., ["UAL", "DAL"])
    bboxobjectGeographic bounding box {north, south, east, west}

    4.3 Event Formats

    flight.departed:

    {
      "type": "flight.departed",
      "timestamp": "2026-01-16T18:30:15.123Z",
      "data": {
        "callsign": "UAL123",
        "flight_uid": 12345,
        "dep": "KLAX",
        "arr": "KJFK",
        "off_utc": "2026-01-16T18:30:00Z"
      }
    }
    

    flight.arrived:

    {
      "type": "flight.arrived",
      "timestamp": "2026-01-16T22:45:30.456Z",
      "data": {
        "callsign": "UAL123",
        "flight_uid": 12345,
        "dep": "KLAX",
        "arr": "KJFK",
        "in_utc": "2026-01-16T22:45:00Z"
      }
    }
    

    flight.positions (batched):

    {
      "type": "flight.positions",
      "timestamp": "2026-01-16T18:30:15.123Z",
      "data": {
        "count": 2847,
        "positions": [
          {
            "callsign": "UAL123",
            "flight_uid": 12345,
            "latitude": 40.1234,
            "longitude": -74.5678,
            "altitude_ft": 35000,
            "groundspeed_kts": 480,
            "heading_deg": 85,
            "vertical_rate_fpm": 0,
            "current_artcc": "ZNY",
            "dep": "KLAX",
            "arr": "KJFK"
          }
        ]
      }
    }
    

    tmi.issued:

    {
      "type": "tmi.issued",
      "timestamp": "2026-01-16T17:00:00.000Z",
      "data": {
        "program_id": "GS_KJFK_20260116",
        "program_type": "GROUND_STOP",
        "airport": "KJFK",
        "start_time": "2026-01-16T17:00:00Z",
        "end_time": "2026-01-16T19:00:00Z",
        "reason": "Thunderstorms"
      }
    }
    

    system.heartbeat:

    {
      "type": "system.heartbeat",
      "timestamp": "2026-01-16T18:30:00Z",
      "data": {
        "connected_clients": 47,
        "uptime_seconds": 86400
      }
    }
    

    4.4 Client Actions

    Ping:

    {"action": "ping"}
    

    Response: {"type": "pong", "timestamp": "..."}

    Status:

    {"action": "status"}
    

    Returns current subscriptions and message counts.

    Unsubscribe:

    {
      "action": "unsubscribe",
      "channels": ["flight.positions"]
    }
    

    4.5 Error Handling

    {
      "type": "error",
      "code": "AUTH_FAILED",
      "message": "Invalid or missing API key"
    }
    

    Error Codes:

    CodeDescription
    AUTH_FAILEDInvalid or expired API key
    CONNECTION_LIMITTier connection limit reached
    RATE_LIMITEDToo many messages per second
    INVALID_JSONMalformed JSON message
    INVALID_CHANNELUnknown channel name
    INVALID_FILTERInvalid filter specification
    MESSAGE_TOO_LARGEMessage exceeds 64KB limit

    5. Data Models

    5.1 GUFI (Globally Unique Flight Identifier)

    Format: VAT-YYYYMMDD-CALLSIGN-DEPT-DEST

    Example: VAT-20260116-UAL123-KLAX-KJFK

    Generation:

    function swim_generate_gufi($callsign, $dept_icao, $dest_icao, $date = null) {
        if ($date === null) $date = gmdate('Ymd');
        return implode('-', ['VAT', $date, strtoupper($callsign), 
                             strtoupper($dept_icao), strtoupper($dest_icao)]);
    }
    

    5.2 Flight Phases

    PhaseDescription
    PREFLIGHTConnected, not yet departed
    DEPARTINGTaxiing for departure
    CLIMBINGAirborne, climbing
    ENROUTECruise altitude
    DESCENDINGDescending to destination
    APPROACHOn approach
    LANDEDWheels down, taxiing
    ARRIVEDAt gate/parked

    5.3 TMI Control Types

    TypeDescription
    GSGround Stop
    GDPGround Delay Program
    MITMiles-in-Trail
    MINITMinutes-in-Trail
    AFPAirspace Flow Program

    5.4 AOC Telemetry Fields

    Virtual Airlines and flight simulator integrations can push telemetry data via the ADL ingest endpoint.

    OOOI Times (Out/Off/On/In):

    FieldDescriptionSource
    out_utcGate departure (pushback)AOC/ACARS
    off_utcWheels up (takeoff)AOC/ACARS
    on_utcWheels down (landing)AOC/ACARS
    in_utcGate arrivalAOC/ACARS
    FMC Times:

    FieldDescriptionSource
    eta_utcEstimated time of arrivalFMC/AOC
    etd_utcEstimated time of departureFMC/AOC
    Position Telemetry:

    FieldDescriptionSource
    vertical_rate_fpmClimb/descent rate (ft/min)Flight sim
    latitudeCurrent positionFlight sim
    longitudeCurrent positionFlight sim
    altitude_ftCurrent altitude (MSL)Flight sim
    heading_degCurrent headingFlight sim
    groundspeed_ktsGround speedFlight sim
    Example: Virtual Airline PIREP Integration

    {
      "flights": [
        {
          "callsign": "VPA123",
          "dept_icao": "KJFK",
          "dest_icao": "KLAX",
          "cid": 1234567,
          "out_utc": "2026-01-16T14:05:00Z",
          "off_utc": "2026-01-16T14:18:00Z",
          "latitude": 40.1234,
          "longitude": -98.5678,
          "altitude_ft": 35000,
          "groundspeed_kts": 485,
          "vertical_rate_fpm": 0,
          "eta_utc": "2026-01-16T18:45:00Z"
        }
      ]
    }
    

    Data Authority Rules:

    The telemetry data source must be authorized to write the field:

  • SIMULATOR source: Authoritative for telemetry fields, can override
  • VIRTUAL_AIRLINE source: Authoritative for airline fields
  • Other sources cannot write telemetry fields unless explicitly allowed
  • 5.5 FIXM Field Mapping

    The API supports both legacy and FIXM-aligned field names via the ?format=fixm parameter.

    Legacy NameFIXM Name
    callsignaircraft_identification
    departuredeparture_aerodrome
    destinationarrival_aerodrome
    cruise_altitudecruising_level
    headingtrack
    ground_speed_ktsground_speed
    altitude_ftaltitude
    phaseflight_status
    wake_categorywake_turbulence
    airline_icaooperator_icao
    outactual_off_block_time
    offactual_time_of_departure
    onactual_landing_time
    inactual_in_block_time

    6. Python SDK

    6.1 Installation

    cd PERTI/sdk/python
    pip install -e .
    

    Or install directly:

    pip install websockets
    

    6.2 Basic Usage

    from swim_client import SWIMClient
    
    

    Create client

    client = SWIMClient('swim_dev_your_key', debug=True)

    Handle events with decorators

    @client.on('connected') def on_connected(info, timestamp): print(f"Connected! Client ID: {info.client_id}") @client.on('flight.departed') def on_departure(event, timestamp): print(f"{event.callsign} departed {event.dep}") @client.on('flight.arrived') def on_arrival(event, timestamp): print(f"{event.callsign} arrived at {event.arr}") @client.on('system.heartbeat') def on_heartbeat(data, timestamp): print(f"Heartbeat: {data.connected_clients} clients")

    Subscribe to channels

    client.subscribe([ 'flight.departed', 'flight.arrived', 'system.heartbeat' ])

    Run (blocking)

    client.run()

    6.3 Filtering

    # Subscribe with airport filter
    client.subscribe(
        channels=['flight.departed', 'flight.arrived'],
        airports=['KJFK', 'KLGA', 'KEWR'],
        artccs=['ZNY']
    )
    
    

    Subscribe with bounding box

    client.subscribe( channels=['flight.positions'], bbox={'north': 42.0, 'south': 39.0, 'east': -72.0, 'west': -76.0} )

    6.4 Async Usage

    import asyncio
    from swim_client import SWIMClient
    
    async def main():
        client = SWIMClient('swim_dev_your_key')
        
        @client.on('flight.departed')
        def on_departure(event, timestamp):
            print(f"{event.callsign} departed")
        
        client.subscribe(['flight.departed'])
        
        await client.connect()
        await client.run_async()
    
    asyncio.run(main())
    

    6.5 SDK Configuration

    ParameterDefaultDescription
    api_keyrequiredAPI key for authentication
    urlwss://perti.vatcscc.org/...WebSocket URL
    reconnectTrueAuto-reconnect on disconnect
    reconnect_interval5.0Initial reconnect delay (seconds)
    max_reconnect_interval60.0Maximum reconnect delay
    ping_interval30.0Ping interval (seconds)
    debugFalseEnable debug logging

    7. Configuration Reference

    7.1 swim_config.php

    Located at PERTI/load/swim_config.php

    API Version:

    define('SWIM_API_VERSION', '1.0.0');
    define('SWIM_API_PREFIX', '/api/swim/v1');
    

    Rate Limits:

    $SWIM_RATE_LIMITS = [
        'system'    => 30000,
        'partner'   => 3000,
        'developer' => 300,
        'public'    => 100
    ];
    

    Key Prefixes:

    $SWIM_KEY_PREFIXES = [
        'system'    => 'swim_sys_',
        'partner'   => 'swim_par_',
        'developer' => 'swim_dev_',
        'public'    => 'swim_pub_'
    ];
    

    Data Sources:

    $SWIM_DATA_SOURCES = [
        // Core sources
        'VATSIM'          => 'vatsim',           // Identity and flight plans
        'vATCSCC'         => 'vatcscc',          // ADL, TMI, demand
    
        // Track/position sources
        'VNAS'            => 'vnas',             // Track data, ATC automation
        'CRC'             => 'crc',              // Track data, tags
        'EUROSCOPE'       => 'euroscope',        // Track data
    
        // ACARS sources
        'ACARS'           => 'acars',            // Generic ACARS (OOOI times)
        'HOPPIE'          => 'hoppie',           // Hoppie ACARS
    
        // Metering sources
        'SIMTRAFFIC'      => 'simtraffic',       // TBFM-style metering
        'TOPSKY'          => 'topsky',           // TopSky EuroScope AMAN
    
        // External sources
        'SIMBRIEF'        => 'simbrief',         // OFP data
        'SIMULATOR'       => 'simulator',        // Pilot sim telemetry
        'VIRTUAL_AIRLINE' => 'virtual_airline',  // VA AOC systems (schedules, CDM)
    
        // Future
        'VFDS'            => 'vfds',             // vFlightDataSystems
    ];
    

    Source Priority Rankings (per FAA CDM spec):

    Data TypePriority Order (highest first)
    Track PositionvNAS → CRC → EuroScope → simulator → ACARS
    OOOI TimesACARS → Virtual Airline → simulator → vATCSCC
    Schedule (STD/STA)Virtual Airline → SimBrief → vATCSCC
    MeteringSimTraffic → vATCSCC → vNAS → TopSky
    General TimesSimTraffic → vATCSCC → vNAS → vFDS → SimBrief → simulator
    CDM Time Fields (FAA ADL T-Field Reference):

    FieldCDM RefDescriptionAuthority
    lrtd_utcT1Airline Runway Time of DepartureVirtual Airline
    lrta_utcT2Airline Runway Time of ArrivalVirtual Airline
    lgtd_utcT3Airline Gate Time of DepartureVirtual Airline
    lgta_utcT4Airline Gate Time of ArrivalVirtual Airline
    ertd_utcT7Earliest Runway Time of DepartureVirtual Airline
    erta_utcT8Earliest Runway Time of ArrivalVirtual Airline
    out_utcT13Actual Off-Block (AOBT)ACARS/VA/sim
    off_utcT11Actual Takeoff (ATOT)ACARS/VA/sim
    on_utcT12Actual Landing (ALDT)ACARS/VA/sim
    in_utcT14Actual In-Block (AIBT)ACARS/VA/sim
    Merge Behaviors:

    BehaviorDescription
    priority_basedHigher priority source always wins (OOOI times)
    immutableOnly authoritative source can write (TMI, schedules)
    variableAccepts newer timestamps (ETAs, metering)
    monotonicRejects older timestamps (position data)
    Cache TTL:

    $SWIM_CACHE_TTL = [
        'flights_list'   => 5,
        'flight_single'  => 3,
        'positions'      => 2,
        'tmi_programs'   => 10,
        'stats'          => 60
    ];
    

    Pagination:

    define('SWIM_DEFAULT_PAGE_SIZE', 100);
    define('SWIM_MAX_PAGE_SIZE', 1000);
    define('SWIM_GEOJSON_PRECISION', 5);
    

    7.2 WebSocket Server Configuration

    $config = [
        'auth_enabled' => true,
        'rate_limit_msg_per_sec' => 10,
        'heartbeat_interval' => 30,
        'max_message_size' => 65536,
        'allowed_origins' => [''],
        'debug' => false
    ];
    

    Tier Connection Limits:

    // WebSocket connection limits (unchanged)
    $tierLimits = [
        'public' => 5,
        'developer' => 50,
        'partner' => 500,
        'system' => 10000
    ];
    


    8. Database Schema

    8.1 swim_api_keys

    Stores API key credentials and permissions.

    CREATE TABLE dbo.swim_api_keys (
        id INT IDENTITY(1,1) PRIMARY KEY,
        api_key NVARCHAR(64) NOT NULL UNIQUE,
        tier NVARCHAR(20) NOT NULL,  -- system, partner, developer, public
        owner_name NVARCHAR(100) NOT NULL,
        owner_email NVARCHAR(255),
        source_id NVARCHAR(50) NULL,
        can_write BIT NOT NULL DEFAULT 0,
        allowed_sources NVARCHAR(MAX) NULL,  -- JSON array
        ip_whitelist NVARCHAR(MAX) NULL,     -- JSON array
        description NVARCHAR(500) NULL,
        expires_at DATETIME2 NULL,
        created_at DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        last_used_at DATETIME2 NULL,
        is_active BIT NOT NULL DEFAULT 1
    );
    

    8.2 swim_audit_log

    Request logging for monitoring and debugging.

    CREATE TABLE dbo.swim_audit_log (
        id BIGINT IDENTITY(1,1) PRIMARY KEY,
        api_key_id INT NULL,
        endpoint NVARCHAR(255) NOT NULL,
        method NVARCHAR(10) NOT NULL,
        ip_address NVARCHAR(45) NOT NULL,
        user_agent NVARCHAR(500) NULL,
        response_status INT NULL,
        response_time_ms INT NULL,
        request_time DATETIME2 NOT NULL DEFAULT GETUTCDATE()
    );
    

    8.3 swim_subscriptions

    WebSocket subscription tracking.

    CREATE TABLE dbo.swim_subscriptions (
        id INT IDENTITY(1,1) PRIMARY KEY,
        api_key_id INT NOT NULL,
        connection_id NVARCHAR(64) NOT NULL,
        channels NVARCHAR(MAX) NOT NULL,     -- JSON array
        filters NVARCHAR(MAX) NULL,          -- JSON object
        connected_at DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        last_ping_at DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        is_active BIT NOT NULL DEFAULT 1,
        FOREIGN KEY (api_key_id) REFERENCES swim_api_keys(id)
    );
    

    8.4 swim_webhook_endpoints

    Webhook registration for push notifications.

    CREATE TABLE dbo.swim_webhook_endpoints (
        id INT IDENTITY(1,1) PRIMARY KEY,
        api_key_id INT NOT NULL,
        endpoint_url NVARCHAR(500) NOT NULL,
        events NVARCHAR(MAX) NOT NULL,       -- JSON array
        secret NVARCHAR(64) NOT NULL,        -- HMAC signing secret
        retry_count INT NOT NULL DEFAULT 3,
        timeout_seconds INT NOT NULL DEFAULT 30,
        last_delivery_at DATETIME2 NULL,
        failure_count INT NOT NULL DEFAULT 0,
        created_at DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        is_active BIT NOT NULL DEFAULT 1,
        FOREIGN KEY (api_key_id) REFERENCES swim_api_keys(id)
    );
    


    9. Deployment & Operations

    9.1 File Structure

    PERTI/
    ├── api/swim/v1/
    │   ├── index.php              # API index
    │   ├── auth.php               # Authentication middleware
    │   ├── flights.php            # Flights endpoint
    │   ├── flight.php             # Single flight endpoint
    │   ├── positions.php          # GeoJSON positions
    │   ├── ingest/                # Data ingestion endpoints
    │   │   ├── adl.php
    │   │   └── track.php
    │   ├── tmi/                   # TMI endpoints
    │   │   ├── programs.php
    │   │   └── controlled.php
    │   └── ws/                    # WebSocket components
    │       ├── WebSocketServer.php
    │       ├── ClientConnection.php
    │       ├── SubscriptionManager.php
    │       └── swim-ws-client.js
    ├── scripts/
    │   ├── swim_ws_server.php     # WebSocket daemon
    │   ├── swim_ws_events.php     # Event detection
    │   └── startup.sh             # Azure startup script
    ├── sdk/python/
    │   ├── swim_client/
    │   │   ├── __init__.py
    │   │   ├── client.py
    │   │   └── events.py
    │   └── examples/
    │       ├── basic_example.py
    │       └── airport_monitor.py
    ├── load/
    │   └── swim_config.php        # Configuration
    └── database/migrations/swim/
        ├── 001_swim_tables.sql
        └── 002_swim_api_database.sql
    

    9.2 Starting WebSocket Server

    # Start daemon
    nohup php /home/site/wwwroot/scripts/swim_ws_server.php --debug > /home/LogFiles/swim_ws.log 2>&1 &
    
    

    Check status

    tail -f /home/LogFiles/swim_ws.log

    Restart

    pkill -f swim_ws_server rm -f /home/site/wwwroot/scripts/swim_ws.lock nohup php /home/site/wwwroot/scripts/swim_ws_server.php --debug > /home/LogFiles/swim_ws.log 2>&1 &

    9.3 Apache WebSocket Proxy

    In startup.sh:

    # Enable proxy modules
    a2enmod proxy proxy_http proxy_wstunnel
    
    

    Add to Apache config

    <Location /api/swim/v1/ws> ProxyPass ws://localhost:8090/ ProxyPassReverse ws://localhost:8090/ </Location>

    9.4 Monitoring

    Check Connected Clients:

    curl -H "Authorization: Bearer swim_sys_internal" \
      "https://perti.vatcscc.org/api/swim/v1/ws/stats"
    

    Audit Log Cleanup:

    EXEC dbo.sp_Swim_CleanupAuditLog @days_to_keep = 90;
    


    10. Implementation Status

    10.1 Phase Summary

    PhaseStatusProgress
    Phase 0: Infrastructure✅ COMPLETE100%
    Phase 1: REST API✅ COMPLETE100%
    Phase 2: WebSocket✅ COMPLETE100%
    Phase 3: SDKs✅ COMPLETEPython, C#, Java, JS

    10.2 Completed Features

  • ✅ Azure SQL Basic database (SWIM_API) - $5/month
  • ✅ API key authentication with tier-based rate limits
  • ✅ All REST endpoints (flights, positions, TMI)
  • ✅ OpenAPI/Swagger documentation
  • ✅ Postman collection
  • ✅ FIXM field naming support
  • ✅ GeoJSON position output
  • ✅ Ratchet WebSocket server (port 8090)
  • ✅ External WSS via Apache proxy
  • ✅ Real-time event detection
  • ✅ Database authentication with key caching
  • ✅ Tier-based connection limits
  • ✅ Python SDK with async support
  • ✅ C# SDK (sdk/csharp/)
  • ✅ Java SDK (sdk/java/)
  • ✅ JavaScript SDK (api/swim/v1/ws/swim-ws-client.js)
  • 10.3 Pending Features

    FeaturePriorityNotes
    Message compressionLowPerformance optimization
    Historical replayLowPast event retrieval
    Metrics dashboardLowUsage tracking
    Redis cachingDeferredFile IPC adequate

    10.4 Contact

  • Email: dev@vatcscc.org
  • Discord: vATCSCC Server
  • Documentation: https://perti.vatcscc.org/docs/swim/

Document generated from PERTI codebase analysis - January 2026*