This guide explains how to set up and use the OpenAIP airspace data integration in SOAR.
SOAR integrates with OpenAIP's REST API to import airspace boundary data and display it on the operations map. This provides pilots with visual awareness of controlled airspace, restricted areas, and other airspace classifications.
OpenAIP data is licensed under CC BY-NC 4.0 (Creative Commons Attribution-NonCommercial 4.0 International)
This means:
- ✅ You may use the data for non-commercial purposes
- ✅ You must provide attribution to OpenAIP
- ❌ You may NOT use this data for commercial purposes without separate licensing
If you plan to use SOAR commercially, you must obtain a commercial license from OpenAIP.
For more information: https://www.openaip.net/legal
- Go to https://www.openaip.net/
- Click "Sign Up" or "Register"
- Create a free account with your email address
- Verify your email address
- Log in to your OpenAIP account
- Navigate to https://www.openaip.net/users/clients
- Click "Create New Client" or "Add Client"
- Fill in the required information:
- Name: SOAR Airspace Integration (or any descriptive name)
- Description: Import airspace data for SOAR flight tracking system
- Click "Create" or "Save"
- IMPORTANT: Copy your API key immediately - it may only be shown once!
- Open your
.envfile in the SOAR project root - Add your OpenAIP API key:
OPENAIP_API_KEY=your_api_key_here
- Save the file
Security Note: Never commit your .env file to version control. The API key should be kept secret.
To perform a complete import of all airspace data globally:
./target/release/soar pull-airspacesThis command will:
- Fetch all airspace data from OpenAIP's API
- Use pagination to retrieve all records (500 per page)
- Rate-limit requests (100ms delay between pages)
- Store airspace boundaries in PostgreSQL with PostGIS geometry
- Log the sync operation in the
airspace_sync_logtable
Expected Duration: 15-30 minutes depending on network speed and total airspace count.
To import airspaces for specific countries only:
./target/release/soar pull-airspaces --countries US,CA,MXUse ISO 3166-1 alpha-2 country codes (US, CA, GB, DE, FR, etc.).
To only fetch airspaces that have been updated since your last successful sync:
./target/release/soar pull-airspaces --incrementalThis uses OpenAIP's updatedAfter parameter to minimize data transfer and processing time.
Recommended: Set up a cron job to run incremental syncs daily:
# Run at 3 AM daily
0 3 * * * cd /path/to/soar && ./target/release/soar pull-airspaces --incrementalOnce airspace data is imported:
- Navigate to the Live Map page (
/live) - Airspaces will automatically load when you zoom in to a specific area
- Visibility Threshold: Airspaces only appear when the map viewport is less than 100,000 square miles
- Color Coding:
- Red: Class A, B, C, D (Controlled airspace)
- Amber: Class E (Controlled airspace - Class E)
- Green: Class F, G (Uncontrolled airspace)
- Gray: Special Use Airspace (SUA) and other types
Click on any airspace boundary to see:
- Airspace name
- Classification (A, B, C, D, E, F, G, SUA)
- Type (CTR, Restricted, Danger, Prohibited, etc.)
- Lower altitude limit
- Upper altitude limit
- Remarks (if available)
You can enable/disable airspace boundaries via the Settings modal:
- Click the Settings button (⚙️) on the operations map
- Toggle "Show Airspace Boundaries" on or off
- Setting is saved to your user preferences
Airspace data is stored in two tables:
Stores airspace boundary geometries and metadata:
CREATE TABLE airspaces (
id UUID PRIMARY KEY,
openaip_id INTEGER UNIQUE,
name TEXT,
airspace_class airspace_class, -- Enum: A, B, C, D, E, F, G, SUA
airspace_type airspace_type, -- Enum: CTR, Restricted, Danger, etc.
country_code CHAR(2),
-- Altitude limits
lower_value INTEGER,
lower_unit TEXT,
lower_reference altitude_reference, -- Enum: MSL, AGL, STD, GND, UNL
upper_value INTEGER,
upper_unit TEXT,
upper_reference altitude_reference,
-- PostGIS geometry (MultiPolygon)
geometry GEOGRAPHY(MultiPolygon, 4326),
geometry_geom GEOMETRY(MultiPolygon, 4326) GENERATED ALWAYS AS (geometry::geometry) STORED,
-- Metadata
remarks TEXT,
activity_type TEXT,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
openaip_updated_at TIMESTAMPTZ
);Spatial Indexes: GIST indexes on both geometry and geometry_geom for fast bounding box queries.
Tracks sync operations for auditing and incremental updates:
CREATE TABLE airspace_sync_log (
id UUID PRIMARY KEY,
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
success BOOLEAN,
airspaces_fetched INTEGER,
airspaces_inserted INTEGER,
countries_filter TEXT[],
updated_after TIMESTAMPTZ
);Airspace data is available via REST API:
GET /data/airspaces?west={west}&south={south}&east={east}&north={north}&limit={limit}
Parameters:
west: Western longitude boundary (-180 to 180)south: Southern latitude boundary (-90 to 90)east: Eastern longitude boundary (-180 to 180)north: Northern latitude boundary (-90 to 90)limit: Maximum results (optional, defaults to 500)
Response: GeoJSON FeatureCollection
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "MultiPolygon",
"coordinates": [...]
},
"properties": {
"id": "uuid",
"openaip_id": 12345,
"name": "San Francisco Class B",
"airspace_class": "B",
"airspace_type": "CTR",
"lower_limit": "SFC",
"upper_limit": "10000 FT MSL",
"remarks": null,
"country_code": "US",
"activity_type": null
}
}
]
}Prometheus metrics are recorded for airspace operations:
airspace_sync.total_fetched- Total airspaces fetched from OpenAIPairspace_sync.total_inserted- Total airspaces inserted/updated in databaseairspace_sync.last_run_timestamp- Unix timestamp of last syncairspace_sync.success- Whether last sync succeeded (1) or failed (0)
api.airspaces.requests- Total API requests to/data/airspacesapi.airspaces.duration_ms- Query duration histogramapi.airspaces.results_count- Number of airspaces returnedapi.airspaces.errors- Error count
Access metrics at: http://localhost:9090 (if Prometheus is configured)
Problem: OPENAIP_API_KEY environment variable not set
Solution: Ensure you've added OPENAIP_API_KEY=your_key_here to your .env file.
Problem: 401 Unauthorized or 403 Forbidden
Solution:
- Verify your API key is correct
- Check that your OpenAIP account is active
- Ensure you haven't exceeded rate limits
Problem: Import is very slow
Solution:
- This is normal for global imports (15-30 minutes)
- Consider country-specific imports for faster initial setup
- Use
--incrementalfor subsequent updates
Problem: Database connection failed
Solution:
- Ensure PostgreSQL is running
- Verify
DATABASE_URLin.envis correct - Check that migrations have been run:
diesel migration run
Problem: Airspaces don't appear on map
Solution:
- Verify data was imported:
psql -d soar_dev -c "SELECT COUNT(*) FROM airspaces;" - Check that you're zoomed in enough (< 100,000 sq miles viewport)
- Verify "Show Airspace Boundaries" is enabled in Settings
- Check browser console for JavaScript errors
Problem: type "geography" does not exist
Solution: Install PostGIS extension:
CREATE EXTENSION IF NOT EXISTS postgis;Problem: Geometry conversion errors
Solution: Verify PostGIS version is 3.0+:
SELECT PostGIS_Version();For large airspace datasets (100,000+ records):
-- Increase work_mem for better query performance
SET work_mem = '256MB';
-- Analyze tables after import
ANALYZE airspaces;
ANALYZE airspace_sync_log;- Airspaces are only loaded when viewport is < 100,000 sq miles
- API requests are debounced (500ms) to prevent excessive calls during panning/zooming
- Results are limited to 500 airspaces per request
- Polygons use low z-index (50) to keep aircraft/airports visible on top
- Base URL: https://api.core.openaip.net
- Authentication:
x-openaip-api-keyheader - Rate Limits: Typically 100 requests per minute (check current limits in API docs)
- Pagination:
page(1-indexed),limit(max 500) - Documentation: https://www.openaip.net/api-docs
OpenAIP updates airspace data regularly as NOTAMs and aeronautical publications change. Recommended sync schedule:
- Daily: Incremental sync (captures updates and new airspaces)
- Weekly: Full sync (ensures data consistency)
- As needed: Country-specific updates when notified of major airspace changes
For issues with:
- SOAR integration: File a GitHub issue at https://github.com/hut8/soar/issues
- OpenAIP API: Contact OpenAIP support at https://www.openaip.net/support
- Data licensing: Contact OpenAIP at https://www.openaip.net/contact
- OpenAIP Website: https://www.openaip.net/
- OpenAIP API Documentation: https://www.openaip.net/api-docs
- OpenAIP Data License: https://www.openaip.net/legal
- PostGIS Documentation: https://postgis.net/docs/
- GeoJSON Specification: https://geojson.org/