Blue API documentation

Get started with the Blue API.

Authenticate with a key, select or create an operation, add a map and an area of operations, then run terrain preparation and use the results for analysis. Every example is available in Bash and Python; Bash is selected by default.

Resource order

Prepare the terrain, then use it for analysis.

Use existing resources when they already exist. Otherwise follow this order:

1

Operation

The top-level workspace. Access to maps and other resources is checked through the operation.

2

Map

A map belongs to an operation. Terrain layers and boundaries belong to a map.

3

Area of operations

A GeoJSON boundary layer on the map. Terrain preparation and later workflows use this polygon.

4

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.

5

Analyze and act

Use the terrain agent, pathfinding, landing-zone surveys, entity-based RF analysis, or other geoprocessing tools with the prepared map.

01 · API key

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.

Configuration
# Production API
export BLUE_API_URL="https://service-blue.exialabs.com"

export BLUE_API_KEY="YOUR_API_KEY"
Use the API hostnameRequests use service-blue.exialabs.com. The corresponding blue... hostname serves the web application, not the API.
02 · Operation

Select an operation or create one.

List the operations available to the account associated with the key.

List operations
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.

Create an operation
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.

Use this operation
export BLUE_OPERATION_ID="YOUR_OPERATION_ID"
03 · Map

Select a map in the operation or create one.

Set BLUE_OPERATION_ID once to the operation ID selected in the previous step.

List maps
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.

Create a map
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.

Use this map
export BLUE_MAP_ID="YOUR_MAP_ID"
04 · Area of operations

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.

List feature collections
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.

Create a boundary feature
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"
05 · Terrain preparation

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.

Start terrain analysis
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.

Use this terrain job
export BLUE_JOB_ID="YOUR_JOB_ID"
06 · Job status

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.

Get terrain 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.

Inspect readiness and phase issues
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}
      ]
    }'
How to interpret the responseanalysis_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 + phases

A 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 checkPhases to checkFeatures enabled
Terrain
sources.elevation.ok
sources.land_cover.ok
Both fields share one raw phase and become ready together.
Raw: terrain_source_artifacts
Rendered map: terrain_display_tiles
Summary: 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.
Roads
sources.roads.ok
Raw: road_artifacts
Rendered map: road_display_tiles
Network: terrain_road_graph
Summary: terrain_summary, which also requires terrain
Road maps and terrain-agent road-network inspection. Together with ready terrain: pathfinding and landing-zone road constraints.
Soil
sources.soil.ok
Raw: soil_artifacts
Rendered map: soil_display_tiles
Soil analysis when the source is ready; soil map rendering when the display phase is ready.
Population
sources.population.ok
Raw: population_artifacts
Rendered map: population_display_tiles
Population analysis when the source is ready; population map rendering when the display phase is ready.
Buildings
sources.buildings.ok
Raw: buildings_artifacts
Rendered 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

readiness

The 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 JSON

This 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_summary is complete, so that agent product is usable even though display_ready is false.
  • sources.buildings.ok is false and buildings_artifacts is failed. Its display phase is blocked, so building analysis and the rendered building layer are not ready.
07 · Reading tiles

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.

Discover terrain tile collections
curl --silent --show-error --fail-with-body \
  -H "Authorization: Bearer ${BLUE_API_KEY}" \
  -H "Accept: application/json" \
  "${BLUE_API_URL}/api/ogc/tiles/collections"
Map-owned tiles are a different catalogUse GET /api/maps/{map_id}/ogc/tiles/collections for products owned by one map, currently RF propagation. Those collections use dynamic layer--UUID IDs.
08 · Choose a feature

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.

Next

Choose a feature guide.

Browse feature guides
09 · Common failures

Check the status code and resource IDs.

401

Key rejected

The bearer token is missing, invalid, expired, or revoked.

403

Access denied

The account does not have access to the selected operation or resource.

404

Resource missing

Check the operation, map, layer, or job ID and its parent resource.

422

Invalid 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.
Other resources and endpoints

Continue to the full Blue API reference.

Open API reference