ArcGIS Integration Guide
How to get AXIOM Exchange property polygons (or lines, or points) onto an ArcGIS map, in either direction the ArcGIS ecosystem expects data.
1. ArcGIS JS API — GeoJSONLayer (recommended)
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) => {
// 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);
});
});
/geo/bbox, /geo/query, and /geo/query/radius all return a proper
FeatureCollection, so those 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.
Styling by reseller or cost key
Every feature carries reseller_id, customer_id, cost_key, and state
in its properties, so you can drive a renderer straight off tenancy
without a second round trip:
const layer = new GeoJSONLayer({
url: "https://your-axiom-host/api/v1/geo/bbox?min_lon=-110&min_lat=25&max_lon=-90&max_lat=50",
renderer: {
type: "unique-value",
field: "reseller_id",
uniqueValueInfos: [
{ value: "7fe24e63-ae59-4183-a4a2-d313e483a64d",
symbol: { type: "simple-fill", color: [88,166,255,0.35], outline: { color: "#58a6ff", width: 1.5 } } },
{ value: "ed4d52c7-67af-4c93-9fb0-1800839737f8",
symbol: { type: "simple-fill", color: [210,153,34,0.35], outline: { color: "#d29922", width: 1.5 } } }
]
}
});
Auth
GeoJSONLayer doesn't attach headers itself — use
esriConfig.request.interceptors, and include the reseller scope if you
want the layer to show only one reseller's properties:
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",
"X-Axiom-Reseller-Id": "7fe24e63-ae59-4183-a4a2-d313e483a64d"
},
});
2. Drawing a polygon in ArcGIS and sending it to AXIOM
The reverse direction: a user sketches an area of interest, and you want every customer and utility status 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 geojsonPolygon = { type: "Polygon", coordinates: event.graphic.geometry.rings };
const headers = { "Content-Type": "application/json", "X-API-Key": "axiom-local-dev-key" };
// Who do I have in this territory?
const customers = await (await fetch("https://your-axiom-host/api/v1/geo/customers/search", {
method: "POST", headers, body: JSON.stringify({ geometry: geojsonPolygon })
})).json();
// What's the utility situation there?
const utilities = await (await fetch("https://your-axiom-host/api/v1/geo/utilities/status", {
method: "POST", headers, body: JSON.stringify({ geometry: geojsonPolygon })
})).json();
console.log(customers.customers, utilities.utilities);
});
});
For anything beyond simple polygons, use a proper conversion library
(e.g. @terraformer/arcgis) rather than reading .rings directly.
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. Every geo endpoint supports
?format=esri:
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": "Austin Distribution Center",
"reseller_id": "7fe24e63-...", "cost_key": "7fe24e63-...", "state": "TX"}
}
]
}
This matches the shape a real ArcGIS Feature Service query returns
(.../FeatureServer/0/query?f=json), so code already written against an
Esri feature service can largely be pointed at AXIOM with a URL change.
4. Publishing AXIOM data into ArcGIS Online / Enterprise
GET /api/v1/geo/bbox?...&format=geojson(or/geo/querywith a large boundary) to pull the full dataset for a reseller or asset type.- Upload the resulting
FeatureCollectionas a GeoJSON item in ArcGIS Online (Content → Add Item → From your computer), or script it with the ArcGIS REST API'saddItem+publishoperations. - For data that needs to stay live, prefer the direct
GeoJSONLayerapproach in section 1 — publishing takes a snapshot.
5. Coordinate system notes
- Storage and every API response are SRID 4326 (WGS84) — longitude
first, then latitude, matching both GeoJSON's
[lon, lat]ordering and the ArcGIS JS API's defaultspatialReference: {wkid: 4326}. - If your ArcGIS deployment works in Web Mercator (
wkid: 102100/3857) internally, the JS API reprojects on the fly when it knows the source is 4326 — no server-side reprojection needed for the common case. If you need geometry pre-projected for a specific client, add a?srid=parameter and reproject with PostGIS'sST_Transformingeo_service.pybefore serializing (not in the base scaffold — a natural first extension point).