Blue API documentation
Feature guides

Follow one workflow from prerequisites through its response and output.

RF workflow

Run RF propagation

Supply transmitter locations and RF values directly, wait for the job, and read the generated map tiles. Entities are optional.

POST/api/terrain-analysis/rf-propagation
01 · Start RF

Provide the transmitter values directly.

This workflow does not require an entity. Supply between one and 32 transmitter locations with their antenna height, frequency, and effective radiated power. This example uses the boundary and center point from Getting Started, so boundary_shape defines the area that will be analyzed.

Instead of a boundary, you can define a circular analysis area with analysis_radius_m on each transmitter or max_radius_m for the request.

Start RF propagation
curl --request POST "$BLUE_API_URL/api/terrain-analysis/rf-propagation" \
  --header "Authorization: Bearer $BLUE_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "map_id": "'"$BLUE_MAP_ID"'",
    "boundary_shape": {
      "type": "Polygon",
      "coordinates": [[
        [-93.1213, 31.1275],
        [-93.1207, 31.0890],
        [-93.0442, 31.0880],
        [-93.0439, 31.1283],
        [-93.1213, 31.1275]
      ]]
    },
    "quality_preset": "balanced",
    "transmitters": [
      {
        "id": "hilltop-relay",
        "name": "Hilltop Relay",
        "latitude": 31.10815,
        "longitude": -93.0826,
        "antenna_height_m": 2.44,
        "frequency_mhz": 51.5,
        "erp_watts": 5
      }
    ]
  }'

Copy the returned job_id.

Use this RF job
export BLUE_RF_JOB_ID="YOUR_JOB_ID"
02 · Poll

Poll until the job succeeds.

Run the curl again until status is success. Stop if it returns failed orcancelled. The Python example performs the polling loop for you.

Poll the RF job
curl --silent --show-error --fail-with-body \
  --header "Authorization: Bearer $BLUE_API_KEY" \
  "$BLUE_API_URL/api/terrain-analysis/rf-propagation/jobs/$BLUE_RF_JOB_ID"
03 · Discover the result

Treat the RF collection as a tiled coverage.

List the map-owned tile collections after the RF job succeeds.

List RF collections
curl --silent --show-error --fail-with-body \
  --header "Authorization: Bearer $BLUE_API_KEY" \
  "$BLUE_API_URL/api/maps/$BLUE_MAP_ID/ogc/tiles/collections"

Copy the returned collection id. RF collection IDs use the formlayer--{map_layer_id}.

Use this RF collection
export BLUE_RF_COLLECTION_ID="layer--YOUR_LAYER_ID"

The collection is the complete RF result. It is divided into square 256 × 256 WebMercatorQuad tiles at each zoom level. A map client requests every tile that intersects its current view and positions those tiles next to one another. Tile URLs use {zoom}/{row}/{column}.png order.

The example below downloads one tile containing the radio location. It is only one piece of the coverage at zoom 12, so opening this file alone will not show the complete RF footprint. Request the neighboring row and column addresses to assemble the rest of the coverage at that zoom.

Download one encoded RF tile
curl --silent --show-error --fail-with-body \
  --header "Authorization: Bearer $BLUE_API_KEY" \
  --output rf-tile-z12-r1675-c988.png \
  "$BLUE_API_URL/api/maps/$BLUE_MAP_ID/ogc/tiles/collections/$BLUE_RF_COLLECTION_ID/tiles/WebMercatorQuad/12/1675/988.png"
04 · Decode and display

Convert each pixel into received power.

These PNGs are lossless data containers, not finished colored map images. Each valid pixel stores the predicted received power at that location in dBm. Image viewers treat the encoded bytes as ordinary colors, so a tile may look strange when opened directly.

  • alpha = 0 means the pixel has no RF data; alpha = 255 means it is valid.
  • encoded = red × 65536 + green × 256 + blue.
  • dBm = -200 + encoded ÷ 100.
  • Choose a useful dBm threshold and color ramp, then apply them to the decoded values.
  • Place every requested tile at its WebMercatorQuad address to render the coverage over a map.

Blue uses this same process: it downloads the visible tiles, decodes their dBm values, hides readings below the selected threshold, applies its signal-strength color ramp and opacity, and joins the tiles on the map.

Alternative · Operation entities

Resolve the transmitter from a radio entity.

If your operation already stores entities in Blue, RF can read the location and completed radio configuration from an entity's communications.radio capability. The operation and map must refer to the same operation, and API keys need the ENTITIES scope.

The example location is the center of the Getting Started boundary. Blue fills in the remaining radio and antenna defaults for these known models.

Create the radio entity
curl --request POST "$BLUE_API_URL/api/operations/$BLUE_OPERATION_ID/entities/" \
  --header "Authorization: Bearer $BLUE_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "profile": {
      "unit_name": "Hilltop Relay",
      "sidc": "10031000001211000000",
      "affiliation": "friendly",
      "capabilities": [
        {
          "id": "primary-radio",
          "type": "communications.radio",
          "schema_version": 1,
          "model": "RT1523_ASIP",
          "config": {
            "network_name": "command",
            "selected_power_level_id": "HI",
            "operating_frequency_mhz": 51.5,
            "antenna": {"model": "AS3900A"}
          }
        }
      ]
    },
    "current_state": {
      "location": {"type": "Point", "coordinates": [-93.0826, 31.10815]}
    }
  }'

Copy the returned entity id.

Use this entity
export BLUE_ENTITY_ID="YOUR_ENTITY_ID"
Start RF from the entity
curl --request POST "$BLUE_API_URL/api/terrain-analysis/rf-propagation/entities" \
  --header "Authorization: Bearer $BLUE_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "map_id": "'"$BLUE_MAP_ID"'",
    "quality_preset": "balanced",
    "entities": [
      {
        "entity_id": "'"$BLUE_ENTITY_ID"'",
        "radio_capability_ids": ["primary-radio"]
      }
    ]
  }'

Copy the returned job_id, then use the same polling, collection discovery, and tile-decoding steps above.

Use this RF job
export BLUE_RF_JOB_ID="YOUR_JOB_ID"