ArcGIS Integration Guide

How to get AXIOM Exchange asset polygons (or lines, or points) onto an ArcGIS map, in either direction the ArcGIS ecosystem expects data.

The ArcGIS JS API's GeoJSONLayer class consumes a GeoJSON FeatureCollection URL directly — no transformation needed. Point it straight at any AXIOM Exchange geo endpoint:

require(["esri/Map", "esri/views/MapView", "esri/layers/GeoJSONLayer"], (Map, MapView, GeoJSONLayer) => {

  // Every asset of a given type, anywhere:
  const solarFarms = new GeoJSONLayer({
    url: "https://your-axiom-host/api/v1/assets?asset_type=solar_farm&format=geojson",
    // Note: GeoJSONLayer expects a static FeatureCollection response.
    // /assets returns a plain list — use /geo/bbox or /geo/query for a
    // ready-made FeatureCollection instead (see below), or a small proxy
    // route that wraps /assets in a FeatureCollection envelope.
  });

  // Everything currently in the map viewport — refresh on extent change:
  function viewportLayer(view) {
    const e = view.extent;
    const url = `https://your-axiom-host/api/v1/geo/bbox` +
      `?min_lon=${e.xmin}&min_lat=${e.ymin}&max_lon=${e.xmax}&max_lat=${e.ymax}`;
    return new GeoJSONLayer({ url });
  }

  const map = new Map({ basemap: "topo-vector" });
  const view = new MapView({ container: "viewDiv", map, center: [-97.74, 30.27], zoom: 9 });

  let currentLayer = viewportLayer(view);
  map.add(currentLayer);

  view.watch("stationary", (isStationary) => {
    if (!isStationary) return;
    map.remove(currentLayer);
    currentLayer = viewportLayer(view);
    map.add(currentLayer);
  });
});

Because /geo/bbox, /geo/query, and /geo/query/radius all return a proper FeatureCollection (not a bare list), those three are the endpoints to point a GeoJSONLayer at directly. /assets and /assets/{id}/geometry return a plain list and a single Feature respectively — fine for fetch()-and-render workflows, but wrap them in a FeatureCollection (or call /geo/bbox with a huge extent) if you need a single GeoJSONLayer URL.

Include auth in the layer's custom request handling, since GeoJSONLayer doesn't attach headers itself — either put a short-lived token in the URL via a signed-URL proxy, or use esriConfig.request.interceptors:

import esriConfig from "@arcgis/core/config";

esriConfig.request.interceptors.push({
  urls: "https://your-axiom-host/api/v1",
  headers: { "X-API-Key": "axiom-local-dev-key" },
});

2. Drawing a polygon in ArcGIS and sending it to AXIOM

The reverse direction: a user sketches an area of interest in the ArcGIS JS API's Sketch widget, and you want every AXIOM asset inside it.

require(["esri/widgets/Sketch", "esri/layers/GraphicsLayer"], (Sketch, GraphicsLayer) => {
  const sketchLayer = new GraphicsLayer();
  map.add(sketchLayer);

  const sketch = new Sketch({ layer: sketchLayer, view, creationMode: "update" });
  view.ui.add(sketch, "top-right");

  sketch.on("create", async (event) => {
    if (event.state !== "complete") return;

    const geometry = event.graphic.geometry; // Esri Polygon geometry
    const geojsonPolygon = arcgisPolygonToGeoJSON(geometry); // see helper below

    const response = await fetch("https://your-axiom-host/api/v1/geo/query", {
      method: "POST",
      headers: { "Content-Type": "application/json", "X-API-Key": "axiom-local-dev-key" },
      body: JSON.stringify({ geometry: geojsonPolygon }),
    });
    const featureCollection = await response.json();
    // featureCollection.features now holds every intersecting AXIOM asset
  });
});

// Esri geometry -> GeoJSON geometry (rings are already lon/lat like GeoJSON;
// this just reshapes the object). For anything beyond simple polygons,
// use @arcgis/core/geometry/support/webMercatorUtils + a proper GeoJSON
// conversion library (e.g. @terraformer/arcgis) instead of hand-rolling it.
function arcgisPolygonToGeoJSON(polygon) {
  return { type: "Polygon", coordinates: polygon.rings };
}

3. Esri JSON / ArcGIS REST-style clients

Older ArcGIS Runtime SDKs (or code written against the ArcGIS REST API's FeatureSet format) expect Esri JSON rather than GeoJSON. Every geo endpoint in AXIOM Exchange supports ?format=esri for exactly this:

GET /api/v1/geo/bbox?min_lon=-98&min_lat=30&max_lon=-97.4&max_lat=30.6&format=esri
{
  "geometryType": "esriGeometryPolygon",
  "spatialReference": {"wkid": 4326},
  "features": [
    {
      "geometry": {"rings": [[...]], "spatialReference": {"wkid": 4326}},
      "attributes": {"id": "...", "name": "...", "asset_type": "solar_farm", "...": "..."}
    }
  ]
}

This matches the shape returned by a real ArcGIS Feature Service query (.../FeatureServer/0/query?f=json), so code already written against an Esri feature service can largely be pointed at AXIOM with just a URL change.

4. Publishing AXIOM data into ArcGIS Online / Enterprise

To get an asset layer into ArcGIS Online as a proper hosted feature layer (rather than calling AXIOM live from a web map):

  1. GET /api/v1/geo/bbox?...&format=geojson (or /geo/query with a large boundary) to pull the full dataset for an organization/asset type.
  2. Upload the resulting FeatureCollection as a GeoJSON item in ArcGIS Online (Content → Add Item → From your computer), or use the ArcGIS REST API's addItem + publish operations to script it.
  3. For data that needs to stay live, prefer the direct GeoJSONLayer approach in section 1 instead — publishing takes a snapshot.

5. Coordinate system notes