Prepare the terrain, then use it for analysis.
Use existing resources when they already exist. Otherwise follow this order:
Operation
The top-level workspace. Access to maps and other resources is checked through the operation.
Map
A map belongs to an operation. Terrain layers and boundaries belong to a map.
Area of operations
A GeoJSON boundary layer on the map. Terrain preparation and later workflows use this polygon.
Prepare terrain data
The terrain-analysis job prepares elevation, slope, land cover, roads, soil, and related map products. Poll it until the data is ready.
Analyze and act
Use the terrain agent, pathfinding, landing-zone surveys, entity-based RF analysis, or other geoprocessing tools with the prepared map.
Configure the API URL and key.
A Blue administrator must create an API key for your account. Python examples use the requests package and the same BLUE_API_KEY environment variable.
# Production API
export BLUE_API_URL="https://service-blue.exialabs.com"
export BLUE_API_KEY="YOUR_API_KEY"service-blue.exialabs.com. The corresponding blue... hostname serves the web application, not the API.Select an operation or create one.
List the operations available to the account associated with the key.
curl --silent --show-error --fail-with-body \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Accept: application/json" \
"${BLUE_API_URL}/api/operations/?force_all=true"If you need a new operation, create one. Otherwise use the ID from the list above.
curl --silent --show-error --fail-with-body \
-X POST \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Content-Type: application/json" \
--data '{
"name": "API Terrain Test",
"unit": "1-23 IN",
"branch": "Army",
"echelon": "Battalion"
}' \
"${BLUE_API_URL}/api/operations/"Set the selected or newly created operation ID once for the remaining examples.
export BLUE_OPERATION_ID="YOUR_OPERATION_ID"Select a map in the operation or create one.
Set BLUE_OPERATION_ID once to the operation ID selected in the previous step.
curl --silent --show-error --fail-with-body \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Accept: application/json" \
"${BLUE_API_URL}/api/maps/?operation_id=${BLUE_OPERATION_ID}"Operations created through the API do not include a map. If the list is empty, create one.
curl --silent --show-error --fail-with-body \
-X POST \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Content-Type: application/json" \
--data '{
"operation_id": "'"${BLUE_OPERATION_ID}"'",
"name": "Terrain Workspace"
}' \
"${BLUE_API_URL}/api/maps/"Set the selected or newly created map ID once for the remaining examples.
export BLUE_MAP_ID="YOUR_MAP_ID"Get or create the terrain boundary.
List the map's feature collections and look for one whose blue:layer_type isboundary. Collection IDs are dynamic layer--UUID values. Follow that collection's advertised items link to read its GeoJSON.
curl --silent --show-error --fail-with-body \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Accept: application/json" \
"${BLUE_API_URL}/api/maps/${BLUE_MAP_ID}/ogc/features/collections"The items response is the GeoJSON FeatureCollection to retain as boundary_shape. If no boundary collection exists, create one with Blue's typed feature endpoint. Its 201response includes the normalized feature_collection, OGC links, and a Locationheader. The terrain example below uses the same geometry. GeoJSON positions use longitude first, latitude second, and the final coordinate closes the polygon.
curl --silent --show-error --fail-with-body \
-X POST \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Content-Type: application/json" \
--data '{
"type": "boundary",
"title": "Area of Operations",
"feature_collection": {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-93.1213, 31.1275],
[-93.1207, 31.0890],
[-93.0442, 31.0880],
[-93.0439, 31.1283],
[-93.1213, 31.1275]
]]
}
}]
}
}' \
"${BLUE_API_URL}/api/maps/${BLUE_MAP_ID}/features"Prepare terrain products for the map.
The API calls this terrain analysis. It generates the terrain data used by the agent and other geoprocessing tools. The example passes the same boundary coordinates created above. Population and buildings default to false, so this guide enables both explicitly because it reads their readiness and tiles.
curl --silent --show-error --fail-with-body \
-X POST \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Content-Type: application/json" \
--data '{
"map_id": "'"${BLUE_MAP_ID}"'",
"boundary_shape": {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-93.1213, 31.1275],
[-93.1207, 31.0890],
[-93.0442, 31.0880],
[-93.0439, 31.1283],
[-93.1213, 31.1275]
]]
}
}]
},
"include_population": true,
"include_buildings": true
}' \
"${BLUE_API_URL}/api/terrain-analysis/"Set the returned job ID once before polling.
export BLUE_JOB_ID="YOUR_JOB_ID"Wait for terrain preparation to finish.
Poll using the BLUE_JOB_ID set in the previous step every few seconds. While status is pending or in_progress, the response is an intermediate progress snapshot. A source may report ok: false with a code such as BUILDINGS_ARTIFACTS_NOT_READY during this time; that means the source is still processing, not that the job has necessarily failed. Results become usable incrementally: as soon as a workflow's required source and phase dependencies are ready, you can read that data and run downstream processing while continuing to poll the parent job.
curl --silent --show-error --fail-with-body \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Accept: application/json" \
"${BLUE_API_URL}/api/terrain-analysis/jobs/${BLUE_JOB_ID}"Stop polling when status becomes success, failed, or cancelled. This is the aggregate result for the parent job, not an all-or-nothing result for every dataset. A failed job can still contain several ready sources and completed phases; it means at least one required source phase failed. A successful job can still have incomplete display products. In every terminal response, inspect the readiness fields, individual sources, and phase details instead of relying on status alone.
curl --silent --show-error --fail-with-body \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Accept: application/json" \
"${BLUE_API_URL}/api/terrain-analysis/jobs/${BLUE_JOB_ID}" \
| jq '{
status,
analysis_ready,
display_ready,
pending_sources: [
.sources | to_entries[] | select(.value.ok == false) |
{source: .key, code: .value.code, message: .value.message}
],
phase_issues: [
.phases[] | select(.status == "failed" or .status == "partial" or .status == "blocked" or .status == "canceled") |
{id, label, status, message, counts}
]
}'analysis_ready: true means all required source artifacts are ready for analysis. display_ready: true means the generated display, graph, and summary phases also completed. When a terminal response is not ready, inspect each sources entry where ok is false, then find the corresponding entry in phases. Its status, message, and counts.failed or counts.skipped identify the affected dataset or product.Match each dataset to its phases
sources + phasesA source is ready when its ok field is true. If it is false while the job is active, keep polling. If it remains false after the job is terminal, use its code and message, then find the matching raw phase for failure details. A derived product is ready only when its own phase has status: "cached" or status: "complete".
| Dataset and source check | Phases to check | Features enabled |
|---|---|---|
Terrainsources.elevation.oksources.land_cover.okBoth fields share one raw phase and become ready together. | Raw: terrain_source_artifactsRendered map: terrain_display_tilesSummary: terrain_summary, which also requires roads | Elevation, slope, ruggedness, and land-cover analysis. Together with ready roads: pathfinding and landing-zone surveys. Radar and RF use elevation but can prepare it on demand. |
Roadssources.roads.ok | Raw: road_artifactsRendered map: road_display_tilesNetwork: terrain_road_graphSummary: terrain_summary, which also requires terrain | Road maps and terrain-agent road-network inspection. Together with ready terrain: pathfinding and landing-zone road constraints. |
Soilsources.soil.ok | Raw: soil_artifactsRendered map: soil_display_tiles | Soil analysis when the source is ready; soil map rendering when the display phase is ready. |
Populationsources.population.ok | Raw: population_artifactsRendered map: population_display_tiles | Population analysis when the source is ready; population map rendering when the display phase is ready. |
Buildingssources.buildings.ok | Raw: buildings_artifactsRendered map: buildings_display_tiles | Building analysis when the source is ready; building map rendering when the display phase is ready. |
Use the top-level fields as a quick summary
readinessThe response has two top-level fields that summarize broad readiness. analysis_ready: true means every raw dataset in the table is ready: terrain, roads, soil, population, and buildings. display_ready: true means every derived product is also ready: all rendered-map phases, terrain_road_graph, and terrain_summary. These are convenient checks for clients that need the complete bundle. A value of false does not mean everything failed; clients using a narrower feature should check only that feature's source and phase dependencies in the table above.
Example: one dataset failed
abbreviated JSONThis terminal response shows why the top-level status is not enough. Buildings failed, but several other source and derived products are ready and usable.
{
"status": "failed",
"analysis_ready": false,
"display_ready": false,
"sources": {
"elevation": { "ok": true, "message": null, "code": null },
"land_cover": { "ok": true, "message": null, "code": null },
"roads": { "ok": true, "message": null, "code": null },
"soil": { "ok": true, "message": null, "code": null },
"population": { "ok": true, "message": null, "code": null },
"buildings": {
"ok": false,
"message": "Building artifact generation failed",
"code": "BUILDINGS_ARTIFACTS_NOT_READY"
}
},
"phases": [
{ "id": "terrain_source_artifacts", "status": "complete" },
{ "id": "road_artifacts", "status": "cached" },
{ "id": "terrain_summary", "status": "complete" },
{
"id": "buildings_artifacts",
"status": "failed",
"counts": { "total": 12, "completed": 8, "failed": 4, "skipped": 0 }
},
{ "id": "buildings_display_tiles", "status": "blocked" }
]
}status: "failed"is terminal, so stop polling. It does not mean every dataset failed.- Terrain and roads have
ok: true, so pathfinding and landing-zone surveys have the raw data they require. terrain_summaryiscomplete, so that agent product is usable even thoughdisplay_readyis false.sources.buildings.okis false andbuildings_artifactsisfailed. Its display phase isblocked, so building analysis and the rendered building layer are not ready.
Discover reusable terrain tiles separately.
Terrain tiles live in the global OGC Tiles service. Follow each collection's advertised tileset andWebMercatorQuad links for blue-native--terrain-elevation,blue-native--terrain-landcover, roads, soil, population, and buildings.
curl --silent --show-error --fail-with-body \
-H "Authorization: Bearer ${BLUE_API_KEY}" \
-H "Accept: application/json" \
"${BLUE_API_URL}/api/ogc/tiles/collections"GET /api/maps/{map_id}/ogc/tiles/collections for products owned by one map, currently RF propagation. Those collections use dynamic layer--UUID IDs.Continue with the workflow you want to build.
You can start retrieving data and running downstream processing as soon as that feature's required sources and phases are ready; the entire terrain analysis does not need to be complete. The feature guides show the exact prerequisites, request, response, and failure behavior for each workflow.
Choose a feature guide.
Check the status code and resource IDs.
401Key rejected
The bearer token is missing, invalid, expired, or revoked.
403Access denied
The account does not have access to the selected operation or resource.
404Resource missing
Check the operation, map, layer, or job ID and its parent resource.
422Invalid request
Check required fields, snake_case names, UUIDs, and GeoJSON coordinates.
- A map must reference an operation available to the key.
- The boundary layer and terrain request must use the same map ID.
- The GeoJSON polygon ring must be closed and use
[longitude, latitude]. - Use the returned job ID when checking terrain-analysis progress.