Subsections of Developer Documentation
Get started
gSuite is the bundle of APIs GEOSPAN offers for fast, detailed geospatial information on structures, such as building roofs. These geospatial APIs allow the user to geoprocess a location: enabling the location to be accurately described and analyzed within a geographic information system (GIS).
The GEOSPAN API allows you to transmit that geospatial information from GEOSPAN to your data sources and users.
Before you begin: Account, API key, and Quota
Before you can successfully call the GEOSPAN API, you need an account, an API key, and some quota. As an individual GEOSPAN user, the process is familiar. If you are part of an organization, account, key, and quota are provisioned differently than if you are a sole GEOSPAN user. For more information on GEOSPAN accounts, see Your Account in the Support Knowledge Base.
Step | Individual GEOSPAN User | Part of an Organization |
---|---|---|
Get an account | Sign up for an account. At geospan.com, select the Sign-Up button. | Request an invite from the GEOSPAN account owner in your organization. |
Get an API key | After you have an account, generate an API key. | Request an API Key from the GEOSPAN account owner in your organization. |
Get quota | Add to your quota with a credit card or promotional code. | Confirm with your organization’s GEOSPAN account owner that quota exists for API calls. |
Overview of GEOSPAN tools for end-users
While you are getting started on the APIs, it may be helpful to understand how the end-user interacts with GEOSPAN technology. End-users have the following interfaces:
- To order a gSquare instant estimate, the user enters an address and selects the structure from the interactive map.
- To order a gPro drawing, the user enters an address, selects the building, and provides additional information.
- View the detailed gPro drawing of a previous order. The user can select from Orders>Complete and be directed to a URL https://apps.geospan.com/gsuite/orders/<order number>/job/<job number>.
Overview of developer interfaces
As a developer, you have access to the following gSuite APIs:
- gSquare: GEOSPAN’s instant estimation API
- gPro: GEOSPAN’s modeling APIs for ordering and retrieving structural drawings
- Spatial: GIS APIs to assist building apps with gSquare and gPro
- Webhooks: Get real-time notifications of events occurring in the GEOSPAN system
Authorization: Api-Key
GEOSPAN REST API is designed to work with API keys in the Authorization header. When calling any GEOSPAN APIs use that API key in the Authorization
header with a bearer string of Api-key
.
headers = {
"Authorization": f"Api-key {GEOSPAN_API_KEY}",
}
res = requests.get(..., headers=headers)
fetch(..., {
headers: {
"Authorization": `Api-key ${GEOSPAN_API_KEY}`,
},
});
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/...' \
-H 'accept: application/json' \
-H 'Authorization: Api-key <geospanapikeystring>'
Additional concepts
You should be all set to work with the GEOSPAN API. Additional concepts, especially around Geospatial and geoprocessing specifications and conventions can be found at Concepts.
gSquare
gSquare is GEOSPAN’s “instant” roof area estimation APIs. gSquare supplies area and predominant pitch in seconds.
Use these APIs to:
Before you begin
Before starting with the gSquare APIs, take time to review the following resources:
- Get Started — set up the right account, API key, and quota
- gSquare examples — review the Python and JavaScript code examples
- Concepts — familiarize yourself with geoprocessing concepts and review the gSquare Lifecycle diagram. This asynchronous approach allows for efficient handling of potentially time-consuming estimation tasks without blocking your application:
- Request: You initiate the lifecycle with a request to the
/estimate/
endpoint to create an estimate. - Get query key: The API returns a query key immediately.
- Poll: You then need to poll the
/query/:queryKey
endpoint to monitor the status of the estimate. - Monitor status: You check the response from the API, which indicates one of these statuses:
PENDING
: The estimate is still being processed.FAILURE
: The estimation process encountered an error.SUCCESS
: The estimate is complete and results are available.
- Act on result:
- If
FAILURE
, an error report is generated. - If
SUCCESS
, read and utilize the results.
- If
- Request: You initiate the lifecycle with a request to the
While you can use the gSquare APIs to get an instant estimate, it is not required when generating an order. This step can be skipped. For information about ordering, see gPro.
Estimating roof areas
The following sections provide an example of the HTTP REST method for each API endpoint, along with explanations of request parameters and an example result that GEOSPAN returns.
POST /estimate
HTTP methodCreate a new area estimation task by providing a roof footprint in Well-Known Text (WKT) format.
curl -X 'POST' \
'https://api.geospan.com/remote4d/v1/gsquare/estimate' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
-H 'Content-Type: application/json' \
-d '{
"wkt": "POINT ( -93.18739 44.71353 )",
"includeImagery": true,
"includeWeather": true
}'
{
"queryKey": "sqm-if_plI1MRIasdf1234lkjh"
}
Parameters
wkt
[required] [type: string] Well-Known Text representation of a roof footprint. Can be a POLYGON or POINT.
includeImagery
[optional] [type: boolean] Toggle whether to include oblique views. Default is false.
includeWeather
[optional] [type: boolean] Toggle whether to include weather data. Default is false.
model
[optional] [type: string] Specify the model to use for estimation. Default is “default”.
GET /query/{query_key}
HTTP methodRetrieve the status and results of a specific estimation task using the query key returned by the POST /estimate
endpoint.
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/gsquare/query/abcd1234-5678-90ef-ghij-klmnopqrstuv' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"computedFootprint": "POLYGON ((-93.187349 44.713629, -93.187347 44.713569, -93.187328 44.713569, -93.187322 44.71344, -93.187381 44.713439, -93.187381 44.713425, -93.187413 44.713425, -93.187414 44.713441, -93.187441 44.713441, -93.18745 44.713627, -93.187349 44.713629))",
"totalArea": {
"area": 197.8059923890073,
"units": "sqm"
},
"pitchResult": {
"primaryPitch": 3,
"deviation": 1
},
"confidence": 6,
"imagery": [
{
"orientation": "nadir",
"image": "/9j/4AAQSkZJRgABAgAAAQABAAD/4QjKaHR0cDov
.
.
.
61TvbxGcBRkY5OakkJkyJGI+lVZoUGQG604os//2Q=="
},
{
"orientation": "north",
"image": "/9j/4AAQSkZJRgABAgAAAQABAAD/4QiwaHR0cDov
.
.
.
WzZUQnbvPeolBsGrn/2Q=="
},
{
"orientation": "east",
"image": "/9j/4AAQSkZJRgABAgAAAQABAAD/4Qi9aHR0cDov
.
.
.
ZP/AIql9al0gwVFPqf/2Q=="
},
{
"orientation": "south",
"image": "/9j/4AAQSkZJRgABAgAAAQABAAD/4QiuaHR0cDov
.
.
.
/+tWcqji9hXR//9k="
},
{
"orientation": "west",
"image": "/9j/4AAQSkZJRgABAgAAAQABAAD/4Qi+aHR0cDov
.
.
.
pnMBiIeNTuZcEdQf5UquF5WjOULM//2Q=="
}
],
"weather": [
{
"datecode": "231024",
"hailSize": 1,
"distance": 9.760984757545051
},
{
"datecode": "240803",
"hailSize": 1,
"distance": 7.845437799202324
}
]
}
Parameters
query_key
[required] [type: string] The unique identifier for the gSquare query.
Subsections of gSquare
API Specification
Before getting started
Before starting with the gSquare API, take time to review Get Started and familiarize yourself with the Concepts.
Examples
Review the Python and JavaScript examples here to see gSquare in action.
Python
"""
Create and monitor a gSquare estimate using a point
"""
import json
import os
import sys
import requests
import time
GEOSPAN_API_KEY = os.getenv("GEOSPAN_API_KEY") or input("Please enter your API key: ")
API_HOME = os.getenv("GEOSPAN_API_HOME", "https://api.geospan.com/remote4d/v1/api/")
# Ensure this point is on a rooftop!
LOCATION = [-93.18736857022286, 44.713507124491315]
def create_estimate(lon: float, lat: float) -> dict:
"""
Use a longitude and latitude to create a request for a
gSquare estimate.
The longitude and latitude should be on a roof top.
"""
url = f"{API_HOME}/gsquare/estimate"
headers = {
"Authorization": f"Api-Key {GEOSPAN_API_KEY}",
}
data = {
"wkt": f"POINT({lon} {lat})",
"includeImagery": False,
"includeWeather": True,
}
res = requests.post(url, headers=headers, json=data)
# Accept both 200 (OK) and 201 (Created) as valid responses
if res.status_code not in (200, 201):
raise ValueError(f"Failed to create estimate. Status code: {res.status_code}, Response: {res.text}")
try:
return res.json()
except json.JSONDecodeError:
raise ValueError(f"Response is not valid JSON. Status code: {res.status_code}, Response: {res.text}")
def check_estimate(query_key: str):
"""
Check the query status
Expected reuslts:
{
"queryKey": "sqm-abcdef12345"
}
"""
url = f"{API_HOME}/gsquare/query/{query_key}"
headers = {
"Authorization": f"Api-Key {GEOSPAN_API_KEY}",
}
res = requests.get(url, headers=headers)
return res.json()
def run_example(silent=False):
"""
Execute a gSquare query with a point.
Expected results:
{
"state": "SUCCESS",
"results": {
"computedFootprint": "POLYGON ((-93.187349 44.713629, -93.187347 44.713569, -93.187328 44.713569, -93.187322 44.71344, -93.187381 44.713439, -93.187381 44.713425, -93.187413 44.713425, -93.187414 44.713441, -93.187441 44.713441, -93.18745 44.713627, -93.187349 44.713629))",
"totalArea": {
"area": 197.8059923890073,
"units": "sqm"
},
"pitchResult": {
"primaryPitch": 3,
"deviation": 1
},
"confidence": 6,
"imagery": [],
"weather": [
{
"datecode": "231024",
"hailSize": 1.0,
"distance": 9.760984757545051
},
{
"datecode": "240803",
"hailSize": 1.0,
"distance": 7.845437799202324
}
]
}
}
"""
# get the lon-lat for the address
# start the gsquare estimate
query_key = create_estimate(LOCATION[0], LOCATION[1])["queryKey"]
# monitor the estimate until it is ready then pretty-print the results
max_polls = 20
while True:
estimate = check_estimate(query_key)
if estimate["state"] != "PENDING":
if not silent:
print(json.dumps(estimate, indent=2))
if estimate["state"] != "SUCCESS":
return 1
return 0
max_polls -= 1
if max_polls == 0:
return 1
time.sleep(2)
if __name__ == "__main__":
if not GEOSPAN_API_KEY:
print("API key is required.")
sys.exit(1) # Exit with non-zero exit code for failure
sys.exit(run_example())
Javascript
An example of using Mapbox and Geospan APIs to replicate gSquare functionality.
Creates a Mapbox GL JS map with building outlines. When buildings are clicked, it produces a gSquare estimate.
The API keys and tokens in index.js are for demonstration only. In a real application, secure them using appropriate methods, such as environment variables, backend proxies, and IAM services with temporary credentials.
// Config
const MAPBOX_ACCESS_TOKEN = "";
const GEOSPAN_API_TOKEN = "";
// Constants
const MARKETPLACE_API_HOME = "https://api.geospan.com/remote4d/v1/api";
const FOOTPRINTS_URL = `${MARKETPLACE_API_HOME}/spatial/footprints`;
const ESTIMATE_URL = `${MARKETPLACE_API_HOME}/gsquare/estimate`;
const ESTIMATE_RESULT_URL = `${MARKETPLACE_API_HOME}/gsquare/query`;
const AUTH_HEADER = { Authorization: `Api-Key ${GEOSPAN_API_TOKEN}` };
const RESULTS_MAX_ATTEMPTS = 20;
const RESULTS_CHECK_DELAY = 2000;
const SQ_FT_PER_SQ_M = 10.7639;
mapboxgl.accessToken = MAPBOX_ACCESS_TOKEN;
// Initialize our map
const map = new mapboxgl.Map({
container: "map", // container ID
center: [-74.568, 39.983], // starting position [lng, lat]
zoom: 19, // starting zoom
style: "mapbox://styles/mapbox/satellite-v9",
});
// Once the map loads, set up our datasources and layers
map.on("load", () => {
// Create a new data source with an empty feature collection
map.addSource("building-footprints", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [],
},
// Make sure all features have a unique ID
generateId: true,
});
// Add a new layer that uses our new data source to create features visible in
// the map
map.addLayer({
id: "building-footprints-layer",
type: "fill",
source: "building-footprints",
layout: {},
paint: {
// Conditional fill-color formatting for highlighting when clicked
"fill-color": [
"case",
["boolean", ["feature-state", "click"], false],
"#FFFF00",
"#0080ff",
],
"fill-opacity": 0.5,
},
});
// Load our footprint data for the first time
loadNewFootprints();
});
// takes a polygon feature and returns its center coordinate as a WKT string
const getCenterWKT = (feature) => {
const bounds = new mapboxgl.LngLatBounds();
feature.geometry.coordinates[0].forEach((coordinate) => {
bounds.extend(coordinate);
});
const center = bounds.getCenter();
return `POINT (${center.lng} ${center.lat})`;
};
// Given the current bounds of the map, load building footprints for that area
// and add them into our building-footprints datasource
const loadNewFootprints = async () => {
const bounds = map.getBounds().toArray().flat();
const params = new URLSearchParams({
bounds,
}).toString();
const footprints = await fetch(`${FOOTPRINTS_URL}?${params}`, {
headers: AUTH_HEADER,
})
.then((data) => data.json())
.catch((e) => displayResults("Could not load footprints"));
if (footprints) {
map.getSource("building-footprints").setData(footprints);
}
};
// Submits and retrieves the results of the estimate
const requestEstimate = async (wkt) => {
// Submit estimate request
const { queryKey } = await fetch(ESTIMATE_URL, {
method: "POST",
headers: {
...AUTH_HEADER,
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
wkt,
includeImagery: true,
includeWeather: true,
}),
}).then((data) => data.json());
// Poll Geospan for results
let counter = RESULTS_MAX_ATTEMPTS;
return new Promise((resolve, reject) => {
const loadResults = () => {
fetch(`${ESTIMATE_RESULT_URL}/${queryKey}`, {
headers: AUTH_HEADER,
})
.then((data) => data.json())
.then(({ state, results }) => {
if (state === "SUCCESS") {
resolve(results);
} else if (state === "PENDING" && counter > 0) {
setTimeout(() => {
loadResults(queryKey);
}, RESULTS_CHECK_DELAY);
} else if (state === "FAILURE") {
reject("There was an error in processing this request.");
} else {
reject("Your request has timed out.");
}
counter--;
})
.catch((e) => reject(e));
};
if (queryKey) {
loadResults(queryKey);
} else {
reject(
"There was an error creating the request. Please select another location or try again in a moment."
);
}
});
};
// Displays the results in the sidebar
const displayResults = (results) => {
document.querySelector("#results").innerHTML = results;
};
let highlightedBuildingId = null;
// Remove highlight from a building and clear results in the sidebar
const clearResults = () => {
if (highlightedBuildingId !== null) {
map.setFeatureState(
{ source: "building-footprints", id: highlightedBuildingId },
{ click: false }
);
}
highlightedBuildingId = null;
displayResults("");
};
// Adds a highlight to a clicked building
const highlightClickedBuilding = (mapboxFeature) => {
clearResults();
map.setFeatureState(
{ source: "building-footprints", id: mapboxFeature.id },
{ click: true }
);
highlightedBuildingId = mapboxFeature.id;
};
// Make sure that every time we pan / zoom the map, we update our building
// footprints
map.on("moveend", () => {
clearResults();
loadNewFootprints();
});
// When we click on a building, highlight the building and request an estimate
map.on("click", "building-footprints-layer", (e) => {
highlightClickedBuilding(e.features[0]);
displayResults("Loading gSquare Estimate...");
// Get the center coordinate of the building and convert it to a WKT string
// that we can use to submit our estimate request
const wkt = getCenterWKT(e.features[0]);
requestEstimate(wkt)
.then((data) =>
displayResults(`
<div><b>Total Area</b>: ${(
data.totalArea.area * SQ_FT_PER_SQ_M
).toFixed(2)} sq ft</div>
<div><b>Primary Pitch</b>: ${data.pitchResult.primaryPitch}</div>
`)
)
.catch((e) => displayResults("Unable to load estimate"));
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>gSquare Lite</title>
<link
href="https://api.mapbox.com/mapbox-gl-js/v3.6.0/mapbox-gl.css"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="map"></div>
<div id="sidebar">
<h1>Click a building to get a gSquare Estimate</h1>
<div id="results"></div>
</div>
<script src="https://api.mapbox.com/mapbox-gl-js/v3.6.0/mapbox-gl.js"></script>
<script src="index.js"></script>
</body>
</html>
html, body {
height: 100%;
width: 100%;
font-family: sans-serif;
}
body {
padding: 0;
margin: 0;
display: flex;
align-content: stretch;
}
#map {
width: 80%;
}
#sidebar {
width: 20%;
padding: 20px;
}
gPro & xPress
gPro is GEOSPAN’s modeling APIs. Use these APIs to order and recall models — geoprocessed structural drawings. Use the gPro APIs to:
- Create and get status on orders
- Export order and download
- Get information about jobs
- Share jobs
- Get information about shared jobs
The gPro API now supports both the standard gPro roof_model
product and the xPress roof_model_express
product. For more information about the xPress model and API implementation, see the xPress Model overview.
The following sections provide an example of the HTTP REST method for each API group, along with explanations of request parameters and an example result that GEOSPAN returns:
- Orders—Create and view orders, which can contain multiple jobs. Export orders to popular file formats and download them.
- POST /order/create: Create a new order with one or more buildings/locations.
- GET /order: Retrieves a paginated list of orders.
- GET /order/{number}: Retrieve details of a specific order by its order number.
- POST /order/{number}/export/: Create an export data task with the desired output format (for example,
docx
,dxf
,esx
,geojson-lines
,geojson-polygons
,symbility-xml
,verisk-xml
, orxml
). - GET /order/{number}/export/{taskId}/: Check that the export task is finished and the data is ready for download.
- GET /order/{number}/export/{taskId}/download/: Download the exported data in the requested format.
- POST /order/preview/ Preview an order before creating it.
- Jobs—Track and manage individual jobs using the Jobs API, accessing various data products (GeoID, oblique and ortho imagery) as they become available.
- GET /jobs/: List and filter jobs with various parameters such as status, date, priority, etc.
- GET /jobs/{id}/: Retrieve detailed information about a specific job.
- GET /jobs/{id}/geoid/: Access the GEOSPAN model format (GeoID) for a completed job.
- GET /jobs/{id}/oblique/: Retrieve oblique imagery for the job from different orientations.
- GET /jobs/{id}/ortho/{layer}/{z}/{x}/{y}/: Access ortho imagery tiles for the job.
- GET/POST/PATCH/DELETE /jobs/{id}/share/: Manage the sharing state of a job, allowing access without authentication. Note that unsharing and then sharing again causes the share key to change.
The gPro API specification is available, complete with Authorization and a “Try it out” feature for each API call.
This document covers gPro APIs. For information about webhooks, see Webhooks.
Create and get status on orders
Call the /order/*
endpoints to create orders and get the status. Orders can include multiple jobs.
GET /order/
HTTP methodCall the /order
endpoint to retrieve a paginated list of orders, with an option to sort by the order status field.
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/order/?limit=2&offset=1000&ordering=number' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"count": 4826,
"next": "http://api.geospan.com/shop/api/gpro/order/?limit=2&offset=1002&ordering=number",
"previous": "http://api.geospan.com/shop/api/gpro/order/?limit=2&offset=998&ordering=number",
"results": [
{
"number": "101073",
"status": "In Process",
"orderedBy": "contact@yourcompany.com",
"referenceId": "141MPBNYHDS",
"customerName": "141MPBNYHDS",
"jobs": [
{
"id": 1057,
"status": "Completed",
"address": "141 Mckinley Parkway, Buffalo, New York 14220",
"buildingInfo": "",
"wkt": "POINT (-78.81471170897164 42.83583933068422)"
}
]
},
{
"number": "101074",
"status": "New",
"orderedBy": "contact@yourcompany.com",
"referenceId": "145MPBNYHDS",
"customerName": "145MPBNYHDS",
"jobs": [
{
"id": 1058,
"status": "Ready",
"address": "145 Mckinley Parkway, Buffalo, New York 14220",
"buildingInfo": "",
"wkt": "POINT (-78.81472199599162 42.83598846524143)"
}
]
}
]
}
Parameters
The GET /order
API requires at least one of the following query parameter fields.
limit
[optional] [type: integer] Number of results to return per page.
offset
[optional] [type: integer] The initial index from which to return the results.
ordering
[optional] [type: string] Which field to use when ordering the results.
GET /order/{number}
HTTP methodcurl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/order/103153' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"number": "103153",
"orderedBy": "contact@yourcompany.com",
"referenceId": "idprovidedbytheorderer",
"customerName": "Contact AtYourCompany",
"jobs": [
{
"id": 3109,
"address": "",
"buildingInfo": "Building number 1",
"wkt": "POINT (-93.18739 44.71353)"
},
{
"id": 3110,
"address": "",
"buildingInfo": "Building number 2",
"wkt": "POINT (-93.1874566 44.7134632)"
}
]
}
Parameters
number
[required] [type: string] The unique order number used to identify and retrieve the order.
POST /order/create
HTTP methodcurl -X 'POST' \
'https://api.geospan.com/remote4d/v1/api/gpro/order/create' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
-H 'Content-Type: application/json' \
-d '{
"products": [
"roof_model_express"
],
"clientName": "Optional Textname",
"referenceId": "Optional Ref ID or Policy Number",
"associatedAddress": "Optional 16288 Fairgreen Ave, Rosemount, MN 55068",
"buildings": [
{
"location": "POINT ( -93.18739 44.71353 )",
"customerNotes":"Optional Building 1 Notes to production...",
"buildingInfo":"Optional Building number 1"
}
],
"customerNotes": "Optional notes to production"
}'
{
"orderNumber": 103156,
"jobIds": [
3113
]
}
curl -X 'POST' \
'https://api.geospan.com/remote4d/v1/api/gpro/order/create' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
-H 'Content-Type: application/json' \
-d '{
"products": [
"roof_model"
],
"clientName": "Optional Textname",
"referenceId": "Optional Ref ID or Policy Number",
"associatedAddress": "Optional 16288 Fairgreen Ave, Rosemount, MN 55068",
"buildings": [
{
"location": "POINT ( -93.18739 44.71353 )",
"customerNotes":"Optional Building 1 Notes to production...",
"buildingInfo":"Optional Building number 1"
}
],
"customerNotes": "Optional notes to production"
}'
{
"orderNumber": 103156,
"jobIds": [
3113
]
}
Parameters
None.
Order schemas and required fields
The POST /order/create
API requires a geometry provided either in the buildings
> location
field or a parcel
field, as well as the products
field set to roof_model
or roof_model_express
.
The POST /order/create
API expects the ExpressCheckout
schema with the ExpressCheckoutBuilding
schema. The following is the schema with descriptions for each field.
{
"products": [
"roof_model"
],
"basketId": "Optional string",
"voucherCode": "Optional string",
"clientName": "Optional Textname",
"referenceId": "Optional Ref ID or Policy Number",
"associatedAddress": "Optional address",
"buildings": [
{
"location": "POINT ( <number_for_longitude> <number_for_latitude> )",
"customerNotes": "Optional notes to production for location 1",
"buildingInfo": "Optional description of building_1"
},
{
"location": "Optional second location",
"customerNotes": "Optional notes to production for location 2",
"buildingInfo": "Optional description of building_2"
}
],
"parcel": {
"wkt": "Required conditionally: if buildings location field not provided"
},
"paymentMethodId": "string"
}
Export order and download
Call the order/{number}/export/
endpoint to export an order to a popular file format. This is a three-step process of initiating an export to a specific file format, waiting for the export to complete, and then downloading it, as in the following pseudocode routine:
-
Create Export Task
taskId = POST /order/{number}/export/?outputFormat={format}
-
Poll Status
WHILE true:
status = GET /order/{number}/export/{taskId}/
IF status == "finished" THEN break
SLEEP 5 seconds
-
Download File
file = GET /order/{number}/export/{taskId}/download/
SAVE file as "order-download.{format}"
POST /order/{number}/export/
HTTP methodThe API to export an order.
roof_model_express
product has one possible value for the outputFormat
: docx
.
outputFormat
are: docx
, dxf
, esx
, geojson-lines
, geojson-polygons
, symbility-xml
, verisk-xml
, or xml
.
This call responds with a taskId
and a status with the possible value of: pending
, finished
, or error
.
curl -X 'POST' \
'https://api.geospan.com/remote4d/v1/api/gpro/order/103618/export/?outputFormat=xml' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"taskId": "1ot3gqxj4q5a2gwz1u3jm1px5",
"status": "pending"
}
curl -X 'POST' \
'https://api.geospan.com/remote4d/v1/api/gpro/order/103618/export/?outputFormat=dfx' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"taskId": "1ot3gqxj4q5a2gwz1u3jm1px5",
"status": "pending"
}
Parameters
outputFormat
[required] [type: string]
The file format of the data to export. Possible values are:
docx
: Word document formatxml
: Standard XML format
The file format of the data to export. Possible values are:
docx
: Word document formatdxf
: AutoCAD DXF formatesx
: ESX formatgeojson-lines
: GeoJSON lines formatgeojson-polygons
: GeoJSON polygons formatsymbility-xml
: Symbility XML formatverisk-xml
: Verisk XML formatxml
: Standard XML format
Export schemas and required fields
number
[required] [type: string] The order number to export.
GET /order/{number}/export/{taskId}/
HTTP methodThe API to get the status of an export task. Possible values are: pending
, finished
, and error
.
curl -X 'GET' \
--location 'https://api.geospan.com/remote4d/v1/api/gpro/order/103689/export/1ot3gqxj4q5a2gwz1u3jm1px5/' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"taskId": "1ot3gqxj4q5a2gwz1u3jm1px5",
"status": "finished"
}
Parameters
None.
Export schemas and required fields
number
[required] [type: string] Order number to export.
taskId
[required] [type: string] Export task ID provided by in the result of a call to POST /order/{number}/export/
.
GET /order/{number}/export/{taskId}/download/
HTTP methodcurl -X 'GET' \
--location 'https://api.geospan.com/remote4d/v1/api/gpro/order/103689/export/1ot3gqxj4q5a2gwz1u3jm1px5/download/' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
--output order-103689-download.xml
The output is saved to a file named order-103689-download.xml in the same directory where the cURL call was made.
Parameters
None.
Download export schemas and required fields
Accept header for downloading
[optional] [type: string] Depending on the type of export you requested, the following are acceptable media types:
text/xml
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/octet-stream
Providing no accept
header type, or providing a type of --header 'accept: */*'
also succeeds.
number
[required] [type: string] Order number to export.
taskId
[required] [type: string] Export task ID provided by in the result of a call to POST /order/{number}/export/
.
output
[optional] [type: string] Depending on the call, provide a location to save the resulting file.
POST /order/{number}/structures/
HTTP methodThe API to export an order projection of the structures JSON data. Available projection
values are crs84
, ecef
, planar
. The default value is crs84
.
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/order/104294/export/?outputFormat=xml' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"kind": "structurecollection",
"structures": [
{
"kind": "structure",
"projection": "crs84",
"points": {
"c101": {
"kind": "corner",
"coordinates": [
-93.38278656215714,
45.01580360496024,
298.0300107039511
]
},
"c102": {
"kind": "corner",
"coordinates": [
-93.3828421751554,
45.01575494707009,
299.70632887631655
]
},
"c103": {
"kind": "corner",
"coordinates": [
-93.38290127794981,
45.01575103014567,
299.70632887631655
]
},
"c104": {
"kind": "corner",
"coordinates": [
-93.38296863682278,
45.01579153831072,
298.03001070581377
]
},
"c105": {
"kind": "corner",
"coordinates": [
-93.38277481641455,
45.0157144388302,
298.03001070581377
]
},
"c106": {
"kind": "corner",
"coordinates": [
-93.38295689080012,
45.015702372199215,
298.0300107030198
]
},
"c107": {
"kind": "corner",
"coordinates": [
-93.38295821479416,
45.015734282841514,
298.1078387647867
]
},
"c108": {
"kind": "corner",
"coordinates": [
-93.38295050971219,
45.01573479344404,
298.31790600530803
]
},
"c109": {
"kind": "corner",
"coordinates": [
-93.38294871302814,
45.015721154472956,
298.31790652964264
]
},
"c110": {
"kind": "corner",
"coordinates": [
-93.38295641906878,
45.01572064380766,
298.1078131068498
]
},
"ground": {
"kind": "ground",
"coordinates": [
-93.38296863682278,
45.015702372199215,
295.1345520019531
]
}
},
"edges": {
"e101": {
"kind": "hip",
"points": [
"c101",
"c102"
],
"properties": {
"length": 7.16
}
},
"e108": {
"kind": "eave",
"points": [
"c101",
"c105"
],
"properties": {
"attachments": [
"gutter"
],
"length": 9.953
}
},
"e102": {
"kind": "ridge",
"points": [
"c103",
"c102"
],
"properties": {
"length": 4.679
}
},
"e103": {
"kind": "hip",
"points": [
"c103",
"c104"
],
"properties": {
"length": 7.16
}
},
"e106": {
"kind": "hip",
"points": [
"c103",
"c106"
],
"properties": {
"length": 7.16
}
},
"e104": {
"kind": "eave",
"points": [
"c104",
"c101"
],
"properties": {
"attachments": [
"gutter"
],
"length": 14.415
}
},
"e109": {
"kind": "eave",
"points": [
"c104",
"c106"
],
"properties": {
"attachments": [
"gutter"
],
"length": 9.953
}
},
"e105": {
"kind": "eave",
"points": [
"c105",
"c106"
],
"properties": {
"attachments": [
"gutter"
],
"length": 14.415
}
},
"e107": {
"kind": "hip",
"points": [
"c105",
"c102"
],
"properties": {
"length": 7.16
}
},
"e110": {
"kind": "chimney",
"points": [
"c108",
"c107"
],
"properties": {
"length": 0.645
}
},
"e111": {
"kind": "chimney",
"points": [
"c108",
"c109"
],
"properties": {
"length": 1.522
}
},
"e112": {
"kind": "chimney",
"points": [
"c109",
"c110"
],
"properties": {
"length": 0.645
}
},
"e113": {
"kind": "chimney",
"points": [
"c107",
"c110"
],
"properties": {
"length": 1.522
}
}
},
"surfaces": {
"surface1": {
"kind": "roof",
"edges": [
[
"e101",
"e102",
"e103",
"e104"
]
],
"properties": {
"material": "asphalt",
"pitch": 4,
"area": 50.135
}
},
"surface2": {
"kind": "roof",
"edges": [
[
"e105",
"e106",
"e107",
"e102"
]
],
"properties": {
"material": "asphalt",
"pitch": 4,
"area": 50.134
}
},
"surface3": {
"kind": "roof",
"edges": [
[
"e107",
"e101",
"e108"
]
],
"properties": {
"material": "asphalt",
"pitch": 4,
"area": 25.621
}
},
"surface4": {
"kind": "roof",
"edges": [
[
"e109",
"e106",
"e103"
],
[
"e110",
"e111",
"e112",
"e113"
]
],
"properties": {
"material": "asphalt",
"pitch": 4,
"area": 24.638
}
}
},
"components": {
"roof": {
"surfaces": [
"surface1",
"surface2",
"surface3",
"surface4"
]
}
}
},
{
"kind": "structure",
"projection": "crs84",
"points": {
"c111": {
"kind": "corner",
"coordinates": [
-93.38296654357835,
45.01588232625001,
297.4300534883514
]
},
"c112": {
"kind": "corner",
"coordinates": [
-93.38296520261137,
45.01580529784941,
297.4300534874201
]
},
"c113": {
"kind": "corner",
"coordinates": [
-93.38301710992096,
45.01584010318367,
298.87778268940747
]
},
"c114": {
"kind": "corner",
"coordinates": [
-93.383017220818,
45.01584647305375,
298.87778268847615
]
},
"c115": {
"kind": "corner",
"coordinates": [
-93.38306778969215,
45.01580439932028,
297.4300534874201
]
},
"c116": {
"kind": "corner",
"coordinates": [
-93.38306913079664,
45.015881427719684,
297.4300534883514
]
},
"ground": {
"kind": "ground",
"coordinates": [
-93.38306913079664,
45.01580439932029,
295.1345520019531
]
}
},
"edges": {
"e114": {
"kind": "eave",
"points": [
"c111",
"c112"
],
"properties": {
"attachments": [
"gutter"
],
"length": 8.561
}
},
"e115": {
"kind": "hip",
"points": [
"c112",
"c113"
],
"properties": {
"length": 5.814
}
},
"e122": {
"kind": "eave",
"points": [
"c112",
"c115"
],
"properties": {
"attachments": [
"gutter"
],
"length": 8.087
}
},
"e116": {
"kind": "ridge",
"points": [
"c113",
"c114"
],
"properties": {
"length": 0.708
}
},
"e117": {
"kind": "hip",
"points": [
"c114",
"c111"
],
"properties": {
"length": 5.825
}
},
"e119": {
"kind": "hip",
"points": [
"c114",
"c116"
],
"properties": {
"length": 5.825
}
},
"e118": {
"kind": "eave",
"points": [
"c115",
"c116"
],
"properties": {
"attachments": [
"gutter"
],
"length": 8.561
}
},
"e120": {
"kind": "hip",
"points": [
"c115",
"c113"
],
"properties": {
"length": 5.814
}
},
"e121": {
"kind": "eave",
"points": [
"c116",
"c111"
],
"properties": {
"attachments": [
"gutter"
],
"length": 8.087
}
}
},
"surfaces": {
"surface5": {
"kind": "roof",
"edges": [
[
"e114",
"e115",
"e116",
"e117"
]
],
"properties": {
"material": "asphalt",
"pitch": 4,
"area": 19.906
}
},
"surface6": {
"kind": "roof",
"edges": [
[
"e118",
"e119",
"e116",
"e120"
]
],
"properties": {
"material": "asphalt",
"pitch": 4,
"area": 19.906
}
},
"surface7": {
"kind": "roof",
"edges": [
[
"e121",
"e117",
"e119"
]
],
"properties": {
"material": "asphalt",
"pitch": 4,
"area": 16.955
}
},
"surface8": {
"kind": "roof",
"edges": [
[
"e120",
"e115",
"e122"
]
],
"properties": {
"material": "asphalt",
"pitch": 4,
"area": 16.892
}
}
},
"components": {
"roof": {
"surfaces": [
"surface5",
"surface6",
"surface7",
"surface8"
]
}
}
}
]
}
Parameters
projection
[optional] [type: string] Available projection
values are crs84
, ecef
, planar
, as in order/104294/structures/?projection=planar
. crs84
is the default value.
POST /order/preview/
HTTP methodThe POST /order/preview/
endpoint takes the same fields as the POST /order/create
endpoint, but provides information about the order basketId
, including total
, discountApplied
, lines
, price
, isComplex
, and voucherCode
.
curl -X 'POST' \
--location 'https://api.geospan.com/remote4d/v1/api/gpro/order/preview' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
--data '{
"products": [
"roof_model"
],
"buildings": [
{
"location": "POINT ( -93.18739 44.71353 )"
}
]
}'
{
"basketId": 3658,
"total": 49.0,
"discountApplied": 0.0,
"lines": [
{
"price": 49.0,
"isComplex": false
}
],
"voucherCode": ""
}
Parameters
None.
Order schemas and required fields
The POST /order/preview
API requires the same fields as the POST /order/create
endpoint and the same ExpressCheckout
schema with the ExpressCheckoutBuilding
schema.
Get information about jobs
Call the /jobs
endpoint to get the details of modeling jobs and to share them.
Construction jobs are often based on parcels. But parcels can contain multiple buildings. So Geospan jobs
are based on individual buildings, not parcels.
GET /jobs/
HTTP methodcurl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/?limit=2' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"count": 3002,
"next": "http://api.geospan.com/shop/api/gpro/jobs/?limit=2&offset=2",
"previous": null,
"results": [
{
"status": "Publish",
"product": {
"upc": "ROOF-S"
},
"url": "http://api.geospan.com/shop/api/jobs/3002/",
"order": {
"url": "http://api.geospan.com/shop/api/orders/2905/",
"id": 2905,
"number": "103041",
"status": "Completed",
"basket": {
"customer_name": "Contact AtYourCompany",
"reference_id": ""
},
"email": "contact@yourcompany.com"
},
"location": {
"type": "Point",
"coordinates": [
-93.18739,
44.71353
]
},
"location_description": "",
"attachments": [],
"date_created": "2024-08-16T14:58:13.230552Z",
"date_updated": "2024-08-16T16:02:22.250881Z",
"status_reason": null,
"id": 3002,
"extra": null,
"production_user": null,
"production_team": "HDS-1",
"customer_notes": "",
"address": "16288 Fairgreen Ave, Rosemount, MN 55068",
"building_info": "",
"siblings": "http://api.geospan.com/shop/api/jobs/3002/siblings/",
"history": "http://api.geospan.com/shop/api/jobs/3002/history/",
"share_key": "0123a45678b9cdef0123a45678b9cdef",
"priority": 5,
"result_type": "geoid",
"result": "{\"geoid\":\"xyz54321-5776-4591-9820-e69994a8bf93\",\"id\":5206}"
},
{
"status": "Publish",
"product": {
"upc": "ROOF-S"
},
"url": "http://api.geospan.com/shop/api/jobs/3001/",
"order": {
"url": "http://api.geospan.com/shop/api/orders/2904/",
"id": 2904,
"number": "103040",
"status": "Completed",
"basket": {
"customer_name": "Contact AtYourCompany",
"reference_id": ""
},
"email": "contact@yourcompany.com"
},
"location": {
"type": "Point",
"coordinates": [
-93.1874566,
44.7134632
]
},
"location_description": "",
"attachments": [],
"date_created": "2024-08-16T13:52:21.766780Z",
"date_updated": "2024-08-16T14:48:23.015383Z",
"status_reason": null,
"id": 3001,
"extra": null,
"production_user": null,
"production_team": "HDS-1",
"customer_notes": "",
"address": "16306 Fairgreen Ave, Rosemount, MN 55068",
"building_info": "",
"siblings": "http://api.geospan.com/shop/api/jobs/3001/siblings/",
"history": "http://api.geospan.com/shop/api/jobs/3001/history/",
"share_key": "3210a45678b9cdef0123a45678b9cdef",
"priority": 5,
"result_type": "geoid",
"result": "{\"geoid\":\"abc12345-e3c1-475f-b82e-237c828f7a32\",\"id\":5205}"
}
]
}
Parameters
address
[optional] [type: string] Filters jobs by the provided address. This is a partial match filter where the provided address string should be contained within the job’s address field.
address__icontains
[optional] [type: string] Filters jobs where the address contains the provided substring. This is case-insensitive.
address__istartswith
[optional] [type: string] Filters jobs where the address starts with the provided substring. This is case-insensitive.
category
[optional] [type: string enum] Filters jobs based on category. Possible values are as follows.
Value | Description |
---|---|
gsquare |
List only gSquare estimates |
gpro |
List only gPro models |
express |
List only xPress models |
This is case-sensitive and must be one of the specified values.
date_created
[optional] [type: string($date-time)] Filters jobs by the exact creation date.
date_created__gt
[optional] [type: string($date-time)] Filters jobs created after the provided date.
date_created__lt
[optional] [type: string($date-time)] Filters jobs created before the provided date.
job_id
[optional] [type: string] Filters jobs by the exact job ID.
job_id__icontains
[optional] [type: string] Filters jobs where the job ID contains the provided substring. This is case-insensitive.
job_id__istartswith
[optional] [type: string] Filters jobs where the job ID starts with the provided substring. This is case-insensitive.
limit
[optional] [type: integer] Number of results to return per page. This parameter controls pagination and helps manage the size of the response. Default is 50.
offset
[optional] [type: integer] The initial index from which to return the results. This parameter is used in pagination to skip a certain number of results before returning the response.
order__basket__customer_name
[optional] [type: string] Filters jobs by customer name within the order’s basket.
order__basket__customer_name__contains
[optional] [type: string] Filters jobs where the customer’s name in the basket contains the provided substring. This is case-insensitive.
order__basket__customer_name__icontains
[optional] [type: string] Filters jobs where the customer’s name in the basket contains the provided substring, case-insensitive.
order__basket__customer_name__startswith
[optional] [type: string] Filters jobs where the customer’s name in the basket starts with the provided substring, case-insensitive.
order__basket__reference_id
[optional] [type: string] Filters jobs by the reference ID within the order’s basket.
ordering
[optional] [type: string] Determines the field by which to order the results. See the table below for possible values.
Value | Description |
---|---|
date_created |
Orders by the date the job was created |
-date_created |
Orders by the date the job was created (descending) |
date_updated |
Orders by the date the job was last updated |
-date_updated |
Orders by the date the job was last updated (descending) |
job_id |
Orders by the unique job ID |
-job_id |
Orders by the unique job ID (descending) |
order__basket__customer_name |
Orders by the customer’s name in the basket |
-order__basket__customer_name |
Orders by the customer’s name in the basket (descending) |
order__basket__reference_id |
Orders by the reference ID of the basket |
-order__basket__reference_id |
Orders by the reference ID of the basket (descending) |
order__number |
Orders by the order number |
-order__number |
Orders by the order number (descending) |
priority |
Orders by the job priority |
-priority |
Orders by the job priority (descending) |
production_team__name |
Orders by the production team’s name |
-production_team__name |
Orders by the production team’s name (descending) |
production_user__email |
Orders by the production user’s email |
-production_user__email |
Orders by the production user’s email (descending) |
status |
Orders by the job status |
-status |
Orders by the job status (descending) |
priority
[optional] [type: integer] Priority level for the job. See the table below for possible values.
Value | Description |
---|---|
1 |
Lowest Priority |
5 |
Standard Priority |
10 |
Rush Priority |
priority__isnot
[optional] [type: string] Filter jobs where the priority is not the specified value.
production_team
[optional] [type: string] Name of the production team assigned to the job.
production_user
[optional] [type: integer] ID of the production user assigned to the job.
production_user__email
[optional] [type: string] Email of the production user assigned to the job.
production_user__email__contains
[optional] [type: string] Filters jobs where the production user’s email contains the specified substring.
production_user__email__icontains
[optional] [type: string] Case-insensitive version of production_user__email__contains.
production_user__email__startswith
[optional] [type: string] Filters jobs where the production user’s email starts with the specified string.
production_user__in
[optional] [type: array[integer]] Filter jobs for a list of production user IDs.
production_user__isnull
[optional] [type: boolean] Filters jobs where the production user is either null or not.
progress
[optional] [type: string] Status of job progress. This parameter might be defined elsewhere.
q
[optional] [type: string] A general search query string.
result__isnull
[optional] [type: boolean] Filters jobs where the result is either null or not.
sort
[optional] [type: array[string]] Fields by which to sort the results. See the table below for possible values.
Value | Description |
---|---|
date_created |
Orders by the date the job was created |
-date_created |
Orders by the date the job was created (descending) |
date_updated |
Orders by the date the job was last updated |
-date_updated |
Orders by the date the job was last updated (descending) |
job_id |
Orders by the unique job ID |
-job_id |
Orders by the unique job ID (descending) |
order__basket__customer_name |
Orders by the customer’s name in the basket |
-order__basket__customer_name |
Orders by the customer’s name in the basket (descending) |
order__basket__reference_id |
Orders by the reference ID of the basket |
-order__basket__reference_id |
Orders by the reference ID of the basket (descending) |
order__number |
Orders by the order number |
-order__number |
Orders by the order number (descending) |
priority |
Orders by the job priority |
-priority |
Orders by the job priority (descending) |
production_team__name |
Orders by the production team’s name |
-production_team__name |
Orders by the production team’s name (descending) |
production_user__email |
Orders by the production user’s email |
-production_user__email |
Orders by the production user’s email (descending) |
status |
Orders by the job status |
-status |
Orders by the job status (descending) |
status
[optional] [type: string enum] Status of the job. Possible values are as follows.
Value | Description |
---|---|
New |
The order is new. |
Pre-Model |
The job is being prepared for modeling. |
Ready |
The job is ready for modeling. |
Modeling |
The job is being modeled. |
QA1 |
The model is ready to be reviewed at the first stage. |
QA1 In Process |
The model is being reviewed at the first stage. |
QA2 |
The model is ready to be reviewed at the second stage. |
QA2 In Process |
The model is being reviewed at the second stage. |
Completed |
The model is complete. |
Publish |
The model is live. |
Canceled |
A job may be canceled due to customer request, imagery issues (quality, availability, or obstructions), technical limitations, ambiguous location, or excessive building size. |
Rejected |
The job was rejected for additional modeling if the design does not meet quality standards or specifications. |
Hold |
The job is awaiting necessary action or information from either the customer or internal team members before it can proceed further. |
Failed QA |
The model could not pass QA. |
status__in
[optional] [type: array[string]] Filters jobs for a list of statuses. See the table below for possible values. Multiple values may be separated by commas.
Value | Description |
---|---|
New |
The order is new. |
Pre-Model |
The job is being prepared for modeling. |
Ready |
The job is ready for modeling. |
Modeling |
The job is being modeled. |
QA1 |
The model is ready to be reviewed at the first stage. |
QA1 In Process |
The model is being reviewed at the first stage. |
QA2 |
The model is ready to be reviewed at the second stage. |
QA2 In Process |
The model is being reviewed at the second stage. |
Completed |
The model is complete. |
Publish |
The model is live. |
Canceled |
A job may be canceled due to customer request, imagery issues (quality, availability, or obstructions), technical limitations, ambiguous location, or excessive building size. |
Rejected |
The job was rejected for additional modeling if the design does not meet quality standards or specifications. |
Hold |
The job is awaiting necessary action or information from either the customer or internal team members before it can proceed further. |
Failed QA |
The model could not pass QA. |
GET /jobs/{id}/
HTTP methodcurl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/2971/' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"status": "Publish",
"product": {
"upc": "ROOF-S"
},
"url": "http://api.geospan.com/shop/api/jobs/2971/",
"order": {
"url": "http://api.geospan.com/shop/api/orders/2874/",
"id": 2874,
"number": "103010",
"status": "Completed",
"basket": {
"customer_name": "Contact AtYourCompany",
"reference_id": ""
},
"email": "contact@yourcompany.com"
},
"location": {
"type": "Point",
"coordinates": [
-93.18739,
44.71353
]
},
"location_description": "",
"attachments": [],
"date_created": "2024-07-25T15:35:13.078159Z",
"date_updated": "2024-07-26T16:34:03.126315Z",
"status_reason": null,
"id": 2971,
"extra": null,
"production_user": null,
"production_team": "HDS-1",
"customer_notes": "note here",
"address": "16288 Fairgreen Ave, Rosemount, MN 55068",
"building_info": "",
"siblings": "http://api.geospan.com/shop/api/jobs/2971/siblings/",
"history": "http://api.geospan.com/shop/api/jobs/2971/history/",
"share_key": "0123a45678b9cdef0123a45678b9cdef",
"priority": 5,
"result_type": "geoid",
"result": "{\"geoid\":\"abc12345-c7df-4e84-ab88-1e758a5c7b88\",\"id\":5191}"
}
Parameters
id
[required] [type: integer] A unique integer value identifying this job. It is needed to specify the exact job you want to retrieve information about. The id
value can be obtained from the result of other API calls, such as listing jobs with GET /jobs/
, or through end-user interfaces.
GET /jobs/{id}/structures/
HTTP methodDRAFT CONTENT Return a Structures JSON structurecollection of all structures on the order.
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/2971/structures/?projection=crs84' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"kind": "structurecollection",
"structures": [
{
"kind": "structure",
"projection": "crs84",
"points": {
"c101": {
"kind": "corner",
"coordinates": [
-93.36791861497224,
45.02530878213521,
278.8077878113836
]
},
"c102": {
"kind": "corner",
"coordinates": [
-93.36786325029368,
45.025347735448214,
280.56030232738703
]
},
"c103": {
"kind": "corner",
"coordinates": [
-93.36780383374325,
45.025347735451795,
280.56030232366174
]
},
"c104": {
"kind": "corner",
"coordinates": [
-93.36774825953246,
45.02530878214529,
278.8077878113836
]
},
"c105": {
"kind": "corner",
"coordinates": [
-93.36791861509695,
45.02538668869866,
278.8077878104523
]
},
"c106": {
"kind": "corner",
"coordinates": [
-93.36782082017419,
45.0253866887355,
278.8077843617648
]
},
"c107": {
"kind": "corner",
"coordinates": [
-93.3677845326412,
45.02536126402634,
279.95164851192385
]
},
"c108": {
"kind": "corner",
"coordinates": [
-93.36778453263756,
45.025366213704366,
279.95164866466075
]
},
"c109": {
"kind": "corner",
"coordinates": [
-93.36774825941929,
45.02539168008893,
278.80778821278363
]
},
"c110": {
"kind": "corner",
"coordinates": [
-93.36782082017369,
45.02539167919033,
278.8077878113836
]
},
"ground": {
"kind": "ground",
"coordinates": [
-93.36791861509695,
45.02530878213523,
275.9885253915563
]
}
},
"edges": {
"e101": {
"kind": "hip",
"points": [
"c101",
"c102"
],
"properties": {
"length": 6.392
}
},
"e112": {
"kind": "eave",
"points": [
"c101",
"c105"
],
"properties": {
"attachments": [
"gutter"
],
"length": 8.658
}
},
"e102": {
"kind": "ridge",
"points": [
"c102",
"c103"
],
"properties": {
"length": 4.683
}
},
"e103": {
"kind": "hip",
"points": [
"c103",
"c104"
],
"properties": {
"length": 6.403
}
},
"e107": {
"kind": "hip",
"points": [
"c103",
"c107"
],
"properties": {
"length": 2.224
}
},
"e104": {
"kind": "eave",
"points": [
"c104",
"c101"
],
"properties": {
"attachments": [
"gutter"
],
"length": 13.427
}
},
"e105": {
"kind": "eave",
"points": [
"c105",
"c106"
],
"properties": {
"attachments": [
"gutter"
],
"length": 7.708
}
},
"e108": {
"kind": "hip",
"points": [
"c105",
"c102"
],
"properties": {
"length": 6.392
}
},
"e106": {
"kind": "valley",
"points": [
"c107",
"c106"
],
"properties": {
"length": 4.18
}
},
"e109": {
"kind": "ridge",
"points": [
"c107",
"c108"
],
"properties": {
"length": 0.55
}
},
"e110": {
"kind": "hip",
"points": [
"c108",
"c109"
],
"properties": {
"length": 4.182
}
},
"e113": {
"kind": "hip",
"points": [
"c108",
"c110"
],
"properties": {
"length": 4.183
}
},
"e111": {
"kind": "eave",
"points": [
"c109",
"c104"
],
"properties": {
"attachments": [
"gutter"
],
"length": 9.213
}
},
"e114": {
"kind": "eave",
"points": [
"c110",
"c109"
],
"properties": {
"attachments": [
"gutter"
],
"length": 5.719
}
},
"e115": {
"kind": "eave",
"points": [
"c106",
"c110"
],
"properties": {
"attachments": [
"gutter"
],
"length": 0.555
}
}
},
"surfaces": {
"surface1": {
"kind": "roof",
"edges": [
[
"e101",
"e102",
"e103",
"e104"
]
],
"properties": {
"material": "asphalt",
"pitch": 5,
"area": 42.29
}
},
"surface2": {
"kind": "roof",
"edges": [
[
"e105",
"e106",
"e107",
"e102",
"e108"
]
],
"properties": {
"material": "asphalt",
"pitch": 5,
"area": 33.573
}
},
"surface3": {
"kind": "roof",
"edges": [
[
"e107",
"e109",
"e110",
"e111",
"e103"
]
],
"properties": {
"material": "asphalt",
"pitch": 5,
"area": 22.125
}
},
"surface4": {
"kind": "roof",
"edges": [
[
"e108",
"e101",
"e112"
]
],
"properties": {
"material": "asphalt",
"pitch": 5,
"area": 20.358
}
},
"surface5": {
"kind": "roof",
"edges": [
[
"e110",
"e113",
"e114"
]
],
"properties": {
"material": "asphalt",
"pitch": 5,
"area": 8.729
}
},
"surface6": {
"kind": "roof",
"edges": [
[
"e109",
"e106",
"e115",
"e113"
]
],
"properties": {
"material": "asphalt",
"pitch": 5,
"area": 1.702
}
}
},
"components": {
"roof": {
"surfaces": [
"surface1",
"surface2",
"surface3",
"surface4",
"surface5",
"surface6"
]
}
}
}
]
}
Parameters
id
[required] [type: integer] A unique integer value identifying this job. It is needed to specify the exact job you want to retrieve structure information about. The id
value can be obtained from the result of other API calls, such as listing jobs with GET /jobs/
, or through end-user interfaces.
GET /jobs/{id}/oblique/
HTTP methodcurl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/2971/oblique/?orientation=n' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
--output 2971_oblique_orientation-n.jpg
The output is saved to a file named 2971_oblique_orientation-n.jpg in the same directory where the cURL call was made.
Parameters
id
[required] [type: integer] A unique integer value identifying the job. It is needed to specify the exact job for which you want to retrieve oblique imagery. The id
value can be obtained from the result of other API calls, such as listing jobs with GET /jobs/
, or from the user interfaces.
orientation
[required] [type: string] Specifies the camera direction relative to the structure for the oblique image. This parameter controls the perspective of the image (e.g., from the north, south, east, or west).
Value | Description |
---|---|
n | North orientation |
e | East orientation |
s | South orientation |
w | West orientation |
GET /jobs/{id}/ortho/{layer}/{z}/{x}/{y}/
HTTP methodcurl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/2971/ortho/base/12/2048/2048/' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
--output 2971_ortho_base-12-2048-2048.jpg
The output is saved to a file named 2971_ortho_base-12-2048-2048.jpg in the same directory where the cURL call was made.
Parameters
id
[required] [type: integer] A unique integer value identifying the job. It is needed to specify the exact job for which you want to retrieve ortho imagery tiles. The id can be obtained from the result of other API calls, such as listing jobs with GET /jobs/, or from user interfaces.
layer
[required] [type: string] The layer to retrieve the ortho imagery from. This could represent different data layers such as different map styles, resolutions, or other types of data layers relevant to the job.
z
[required] [type: string] The tile zoom level. This parameter controls how much detail the tile contains, with higher zoom levels representing more detailed imagery.
x
[required] [type: string] The x-coordinate of the tile in the tile grid. This is used to locate the specific tile in the grid at the given zoom level.
y
[required] [type: string] The y-coordinate of the tile in the tile grid. This, along with the x-coordinate, identifies the specific tile at the given zoom level.
Share jobs
roof_model_express
product.
When a job is shared, it receives a share_key
that can be used to access job data through the shared-jobs endpoints without requiring an API key or authentication token. This endpoint is particularly useful for creating shared access to job data, enabling collaboration or viewing by external parties without the need for full access.
When you share a job, the URL is in the form https://apps.geospan.com/gsuite/shared/<shared_key>
.
If you unshare and then share again, the share key changes. Get the updated share key to forward to individuals.
Security Considerations: The share_key
is a critical security element. Anyone with this key can access the job details, so it should be shared cautiously and only with trusted parties. This key should be kept secure, as it provides direct access to job information. Consider implementing expiration mechanisms or other security controls depending on your application’s requirements.
Rate Limiting and Quota: As with other API endpoints, be mindful of potential limits when accessing shared jobs, especially if automating requests or sharing with multiple users.
GET /jobs/{id}/share/
HTTP method
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/2971/share/' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{"share_key":"12345ab67890cd12345ab67890cd"}
Parameters
id
[required] [type: integer] A unique integer value identifying the job. It is needed to specify the exact job for which you want to retrieve the share key. The id can be obtained from the result of other API calls, such as listing jobs with GET /jobs/, or from user interfaces.
POST /jobs/{id}/share/
HTTP method
curl -X 'POST' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/3002/share/' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{"share_key":"0987z8765y6543w0987z8765y6543w"}
Parameters
id
[required] [type: integer] A unique integer value identifying the job. It is needed to specify the exact job for which you want to create a share key. The id can be obtained from the result of other API calls, such as listing jobs with GET /jobs/, or from user interfaces.
PATCH /jobs/{id}/share/
This PATCH jobs/{id}/share
call toggles the share_key
between a new share key and an empty string.
The share key can be set as a call to POST /jobs/{id}/share/
or through the Share button on the user interface for the job. If a share key has not been set through these other means, calling PATCH on the jobs/{id}/share
endpoint for the first time sets an initial value of the share key. Its function, however, is to toggle the share state.
HTTP method
curl -X 'PATCH' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/3002/share/' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
-H 'Content-Type: application/json' \
-d '{"share_key": "8765lkj4321oiuy0m9n8n9876grd32"}'
{"share_key":"8765lkj4321oiuy0m9n8n9876grd32"}
Parameters
id
[required] [type: integer] A unique integer value identifying the job. It is needed to specify the exact job for which you want to update the share key value. The id can be obtained from the result of other API calls, such as listing jobs with GET /jobs/, or from user interfaces.
- DELETE /jobs/{id}/share/
curl -X 'DELETE' \
'https://api.geospan.com/remote4d/v1/api/gpro/jobs/2971/share/' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
No message returned.
Parameters
id
[required] [type: integer] A unique integer value identifying the job. It is needed to specify the exact job for which you want to delete the share key value. The id can be obtained from the result of other API calls, such as listing jobs with GET /jobs/, or from user interfaces.
Get information about shared jobs
The /shared-jobs/{share_key}/
endpoint provides access to the details of a shared job using a share_key
. This endpoint is useful for retrieving job information without requiring full authentication, making it ideal for sharing job details with external parties or collaborators. The share_key
serves as a secure, unique identifier that provides access to the specific job data.
The share_key
is a unique string generated when a job is shared. It acts as a secure token that allows access to job details without requiring standard API authentication. This key should be kept secure, as it provides direct access to job information.
Retrieve the share_key
from the response of a POST /jobs/{id}/share/
or PATCH /jobs/{id}/share/
request, where it is created or updated. You can also get the share_key
from GET /jobs/{id}/share/, and from the end-user interface.
GET /shared-jobs/{share_key}/
HTTP method
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/shared-jobs/0123a45678b9cdef0123a45678b9cdef/' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"status": "Publish",
"product": {
"upc": "ROOF-S"
},
"url": "http://api.geospan.com/shop/api/jobs/2856/",
"order": {
"url": "http://api.geospan.com/shop/api/orders/2761/",
"id": 2761,
"number": "102895",
"status": "Completed",
"basket": {
"customer_name": "Your company orderer",
"reference_id": "E2E100"
},
"email": "orderer@yourcompany.com"
},
"location": {
"type": "Point",
"coordinates": [
-93.18739,
44.71516
]
},
"location_description": "",
"attachments": [],
"date_created": "2024-03-18T19:44:07.583350Z",
"date_updated": "2024-08-26T20:27:11.414115Z",
"status_reason": null,
"id": 2856,
"extra": {
"origin": "verisk",
"origin_id": "1234abcd-0987-5678-xyz1-1234asdf9876"
},
"production_user": null,
"production_team": "QAE-1",
"customer_notes": "",
"address": "16162 Fairgreen Ave, Rosemount, MN 55068",
"building_info": "",
"siblings": "http://api.geospan.com/shop/api/jobs/2856/siblings/",
"history": "http://api.geospan.com/shop/api/jobs/2856/history/",
"share_key": "03ec238cb2a9b193ecda1b497c83871a",
"priority": 5,
"result_type": "geoid",
"result": "{\"geoid\":\"9876zyxw-098z-123a-456b-78901234asdf\",\"id\":5089}"
}
share_key
[Required][type:string] Any valid share_key
string (for example, 0123a45678b9cdef0123a45678b9cdef
). A unique identifier used to access a shared job, this key is generated when a job is shared.
GET /shared-jobs/{share_key}/geoid/
HTTP method
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/shared-jobs/0123a45678b9cdef0123a45678b9cdef/geoid/' \
-H 'accept: application/json' \
-H 'Authorization: Api-Key <geospanapikeystring>'
{
"id": 5089,
"status": "D",
"geoid": "537cd2a5-a311-41ec-b4f5-43aa0c36e6d0",
"roof_model": "{\"content\":[{\"ParcelID\":\"job2856\",\"BldgNum\":\"1\",\"ComponNum\":\"1\",\"GraphicJson\":\"{\\\"groundElev\\\":284.2817687988281,\\\"hingePt\\\":null,\\\"corners\\\":{\\\"53fc4d11-d6d0-6694-b304-4cb43e7c03c9\\\":{\\\"x\\\":-252433.40573928275,\\\"y\\\":-4533102.750433343,\\\"z\\\":4465112.13824828},\\\"ca432e78-4c47-309d-03bf-0055b18aaf14\\\":{\\\"x\\\":-252433.4697731101,\\\"y\\\":-4533104.741977499,\\\"z\\\":4465108.06719631},\\\"a83e254a-8d0b-2844-e519-f2be5f4df9ca\\\":{\\\"x\\\":-252445.1894685201,\\\"y\\\":-4533104.17409267,\\\"z\\\":4465107.981158005},\\\"98caebe7-f52d-de0e-89fa-adbdd3dc0af6\\\":{\\\"x\\\":-252445.1251123508,\\\"y\\\":-4533102.182634073,\\\"z\\\":4465112.052281542}},\\\"walls\\\":[{\\\"corner1\\\":\\\"ca432e78-4c47-309d-03bf-0055b18aaf14\\\",\\\"corner2\\\":\\\"53fc4d11-d6d0-6694-b304-4cb43e7c03c9\\\",\\\"wallType\\\":\\\"r\\\"},{\\\"corner1\\\":\\\"a83e254a-8d0b-2844-e519-f2be5f4df9ca\\\",\\\"corner2\\\":\\\"ca432e78-4c47-309d-03bf-0055b18aaf14\\\",\\\"wallType\\\":\\\"e\\\"},{\\\"corner1\\\":\\\"98caebe7-f52d-de0e-89fa-adbdd3dc0af6\\\",\\\"corner2\\\":\\\"a83e254a-8d0b-2844-e519-f2be5f4df9ca\\\",\\\"wallType\\\":\\\"r\\\"},{\\\"corner1\\\":\\\"53fc4d11-d6d0-6694-b304-4cb43e7c03c9\\\",\\\"corner2\\\":\\\"98caebe7-f52d-de0e-89fa-adbdd3dc0af6\\\",\\\"wallType\\\":\\\"d\\\"}],\\\"cornersOrder\\\":[[-252433.40573928275,-4533102.750433343,4465112.13824828],[-252433.4697731101,-4533104.741977499,4465108.06719631],[-252445.1894685201,-4533104.17409267,4465107.981158005],[-252445.1251123508,-4533102.182634073,4465112.052281542]],\\\"roomCtrlPts\\\":[{\\\"roomName\\\":\\\"job2856&1&1&dn2qi\\\",\\\"myCtrl\\\":[\\\"a83e254a-8...,ca432e78-4c...\\\",\\\"98caebe...\\\"],\\\"ctrl2Pt\\\":true,\\\"materialType\\\":null,\\\"poiObjs\\\":[]}],\\\"cutoutParent\\\":null,\\\"cutoutType\\\":null}\",\"LevelNum\":1,\"tempID\":\"job2856@1@1@dn2qi\"},{\"ParcelID\":\"job2856\",\"BldgNum\":\"1\",\"ComponNum\":\"2\",\"GraphicJson\":\"{\\\"groundElev\\\":284.2817687988281,\\\"hingePt\\\":null,\\\"corners\\\":{\\\"53fc4d11-d6d0-6694-b304-4cb43e7c03c9\\\":{\\\"x\\\":-252433.40573928275,\\\"y\\\":-4533102.750433343,\\\"z\\\":4465112.13824828},\\\"98caebe7-f52d-de0e-89fa-adbdd3dc0af6\\\":{\\\"x\\\":-252445.1251123508,\\\"y\\\":-4533102.182634073,\\\"z\\\":4465112.052281542},\\\"f45af621-70c9-b273-0003-cf034d661d04\\\":{\\\"x\\\":-252444.946114973,\\\"y\\\":-4533098.129825465,\\\"z\\\":4465114.088580731},\\\"b7952dc3-7255-df15-3b6c-295637d75241\\\":{\\\"x\\\":-252438.85690594575,\\\"y\\\":-4533098.424884663,\\\"z\\\":4465114.133286617},\\\"4e441b32-91a9-f41d-c4c4-1595c8f07df8\\\":{\\\"x\\\":-252438.2768597194,\\\"y\\\":-4533099.027264776,\\\"z\\\":4465113.84981524},\\\"efd601d1-5983-20c1-30e9-3bcf8d201988\\\":{\\\"x\\\":-252437.6433304065,\\\"y\\\":-4533098.481918708,\\\"z\\\":4465114.143109792},\\\"9037c3cf-e7ca-ff7b-2001-25e16b15608c\\\":{\\\"x\\\":-252433.22314167113,\\\"y\\\":-4533098.696102111,\\\"z\\\":4465114.17556043}},\\\"walls\\\":[{\\\"corner1\\\":\\\"53fc4d11-d6d0-6694-b304-4cb43e7c03c9\\\",\\\"corner2\\\":\\\"98caebe7-f52d-de0e-89fa-adbdd3dc0af6\\\",\\\"wallType\\\":\\\"d\\\"},{\\\"corner1\\\":\\\"f45af621-70c9-b273-0003-cf034d661d04\\\",\\\"corner2\\\":\\\"98caebe7-f52d-de0e-89fa-adbdd3dc0af6\\\",\\\"wallType\\\":\\\"r\\\"},{\\\"corner1\\\":\\\"b7952dc3-7255-df15-3b6c-295637d75241\\\",\\\"corner2\\\":\\\"f45af621-70c9-b273-0003-cf034d661d04\\\",\\\"wallType\\\":\\\"g\\\"},{\\\"corner1\\\":\\\"b7952dc3-7255-df15-3b6c-295637d75241\\\",\\\"corner2\\\":\\\"4e441b32-91a9-f41d-c4c4-1595c8f07df8\\\",\\\"wallType\\\":\\\"n\\\"},{\\\"corner1\\\":\\\"efd601d1-5983-20c1-30e9-3bcf8d201988\\\",\\\"corner2\\\":\\\"4e441b32-91a9-f41d-c4c4-1595c8f07df8\\\",\\\"wallType\\\":\\\"n\\\"},{\\\"corner1\\\":\\\"efd601d1-5983-20c1-30e9-3bcf8d201988\\\",\\\"corner2\\\":\\\"9037c3cf-e7ca-ff7b-2001-25e16b15608c\\\",\\\"wallType\\\":\\\"e\\\"},{\\\"corner1\\\":\\\"9037c3cf-e7ca-ff7b-2001-25e16b15608c\\\",\\\"corner2\\\":\\\"53fc4d11-d6d0-6694-b304-4cb43e7c03c9\\\",\\\"wallType\\\":\\\"r\\\"}],\\\"cornersOrder\\\":[[-252433.40573928275,-4533102.750433343,4465112.13824828],[-252445.1251123508,-4533102.182634073,4465112.052281542],[-252444.946114973,-4533098.129825465,4465114.088580731],[-252438.85690594575,-4533098.424884663,4465114.133286617],[-252438.2768597194,-4533099.027264776,4465113.84981524],[-252437.6433304065,-4533098.481918708,4465114.143109792],[-252433.22314167113,-4533098.696102111,4465114.17556043]],\\\"roomCtrlPts\\\":[{\\\"roomName\\\":\\\"job2856&1&2&dbz95\\\",\\\"myCtrl\\\":[\\\"53fc4d11-d...,98caeb...\\\",\\\"efd601...\\\"],\\\"ctrl2Pt\\\":true,\\\"materialType\\\":null,\\\"poiObjs\\\":[]}],\\\"cutoutParent\\\":null,\\\"cutoutType\\\":null}\",\"LevelNum\":1,\"tempID\":\"job2856@1@2@dbz95\"},{\"ParcelID\":\"job2856\",\"BldgNum\":\"1\",\"ComponNum\":\"3\",\"GraphicJson\":\"{\\\"groundElev\\\":284.2817687988281,\\\"hingePt\\\":null,\\\"corners\\\":{\\\"072c321f-bb19-9243-492a-07856554145b\\\":{\\\"x\\\":-252438.00459117617,\\\"y\\\":-4533092.392307089,\\\"z\\\":4465120.555984414},\\\"c7f1a239-2039-3b40-e5b7-0ed5a7d2ea47\\\":{\\\"x\\\":-252432.98290329005,\\\"y\\\":-4533091.44294743,\\\"z\\\":4465119.412825007},\\\"0310919c-e265-d9eb-799b-9dc732ab6e21\\\":{\\\"x\\\":-252433.25517203115,\\\"y\\\":-4533098.0779082095,\\\"z\\\":4465112.706662344},\\\"0b882747-9416-8002-169f-c7576f446814\\\":{\\\"x\\\":-252433.56301924028,\\\"y\\\":-4533098.13588638,\\\"z\\\":4465112.776968592},\\\"8dbf0af3-1452-4518-dd70-0fff099da0de\\\":{\\\"x\\\":-252437.66080003206,\\\"y\\\":-4533098.907638827,\\\"z\\\":4465113.712821135},\\\"e21a7927-bd73-72b2-fc09-feec565e7bc6\\\":{\\\"x\\\":-252437.64333040648,\\\"y\\\":-4533098.481918709,\\\"z\\\":4465114.143109792},\\\"cb4688dd-85c0-da55-999a-f27e95dbf79f\\\":{\\\"x\\\":-252438.27685971936,\\\"y\\\":-4533099.027264776,\\\"z\\\":4465113.849815241}},\\\"walls\\\":[{\\\"corner1\\\":\\\"072c321f-bb19-9243-492a-07856554145b\\\",\\\"corner2\\\":\\\"c7f1a239-2039-3b40-e5b7-0ed5a7d2ea47\\\",\\\"wallType\\\":\\\"r\\\"},{\\\"corner1\\\":\\\"c7f1a239-2039-3b40-e5b7-0ed5a7d2ea47\\\",\\\"corner2\\\":\\\"0310919c-e265-d9eb-799b-9dc732ab6e21\\\",\\\"wallType\\\":\\\"e\\\"},{\\\"corner1\\\":\\\"0b882747-9416-8002-169f-c7576f446814\\\",\\\"corner2\\\":\\\"0310919c-e265-d9eb-799b-9dc732ab6e21\\\",\\\"wallType\\\":\\\"r\\\"},{\\\"corner1\\\":\\\"8dbf0af3-1452-4518-dd70-0fff099da0de\\\",\\\"corner2\\\":\\\"0b882747-9416-8002-169f-c7576f446814\\\",\\\"wallType\\\":\\\"s\\\"},{\\\"corner1\\\":\\\"e21a7927-bd73-72b2-fc09-feec565e7bc6\\\",\\\"corner2\\\":\\\"8dbf0af3-1452-4518-dd70-0fff099da0de\\\",\\\"wallType\\\":\\\"n\\\"},{\\\"corner1\\\":\\\"e21a7927-bd73-72b2-fc09-feec565e7bc6\\\",\\\"corner2\\\":\\\"cb4688dd-85c0-da55-999a-f27e95dbf79f\\\",\\\"wallType\\\":\\\"v\\\"},{\\\"corner1\\\":\\\"cb4688dd-85c0-da55-999a-f27e95dbf79f\\\",\\\"corner2\\\":\\\"072c321f-bb19-9243-492a-07856554145b\\\",\\\"wallType\\\":\\\"d\\\"}],\\\"cornersOrder\\\":[[-252438.00459117617,-4533092.392307089,4465120.555984414],[-252432.98290329005,-4533091.44294743,4465119.412825007],[-252433.25517203115,-4533098.0779082095,4465112.706662344],[-252433.56301924028,-4533098.13588638,4465112.776968592],[-252437.66080003206,-4533098.907638827,4465113.712821135],[-252437.64333040648,-4533098.481918709,4465114.143109792],[-252438.27685971936,-4533099.027264776,4465113.849815241]],\\\"roomCtrlPts\\\":[{\\\"roomName\\\":\\\"job2856&1&3&pipxg4\\\",\\\"myCtrl\\\":[\\\"cb4688dd-8...,072c321f-bb...\\\",\\\"c7f1a2...\\\"],\\\"ctrl2Pt\\\":true,\\\"materialType\\\":null,\\\"poiObjs\\\":[]}],\\\"cutoutParent\\\":null,\\\"cutoutType\\\":null}\",\"LevelNum\":1,\"tempID\":\"job2856@1@3@pipxg4\"},{\"ParcelID\":\"job2856\",\"BldgNum\":\"1\",\"ComponNum\":\"4\",\"GraphicJson\":\"{\\\"groundElev\\\":284.2817687988281,\\\"hingePt\\\":null,\\\"corners\\\":{\\\"6dc7bdf0-2542-c997-a614-cdb8d952c323\\\":{\\\"x\\\":-252442.8902726021,\\\"y\\\":-4533090.963113398,\\\"z\\\":4465119.3403225895},\\\"072c321f-bb19-9243-492a-07856554145b\\\":{\\\"x\\\":-252438.00459117617,\\\"y\\\":-4533092.392307089,\\\"z\\\":4465120.555984414},\\\"cb4688dd-85c0-da55-999a-f27e95dbf79f\\\":{\\\"x\\\":-252438.27685971936,\\\"y\\\":-4533099.027264776,\\\"z\\\":4465113.849815241},\\\"e594d0d7-a6c3-edc3-28e4-21a546b67f16\\\":{\\\"x\\\":-252438.85690594578,\\\"y\\\":-4533098.424884664,\\\"z\\\":4465114.133286617},\\\"a91f98ce-f98b-b86f-5858-4a3d646ea22b\\\":{\\\"x\\\":-252438.87446771425,\\\"y\\\":-4533098.852850227,\\\"z\\\":4465113.700728418},\\\"3c917bde-4a92-0593-7e14-3abeea730ff4\\\":{\\\"x\\\":-252443.16254134322,\\\"y\\\":-4533097.598074179,\\\"z\\\":4465112.634159926}},\\\"walls\\\":[{\\\"corner1\\\":\\\"6dc7bdf0-2542-c997-a614-cdb8d952c323\\\",\\\"corner2\\\":\\\"072c321f-bb19-9243-492a-07856554145b\\\",\\\"wallType\\\":\\\"r\\\"},{\\\"corner1\\\":\\\"cb4688dd-85c0-da55-999a-f27e95dbf79f\\\",\\\"corner2\\\":\\\"072c321f-bb19-9243-492a-07856554145b\\\",\\\"wallType\\\":\\\"d\\\"},{\\\"corner1\\\":\\\"e594d0d7-a6c3-edc3-28e4-21a546b67f16\\\",\\\"corner2\\\":\\\"cb4688dd-85c0-da55-999a-f27e95dbf79f\\\",\\\"wallType\\\":\\\"v\\\"},{\\\"corner1\\\":\\\"e594d0d7-a6c3-edc3-28e4-21a546b67f16\\\",\\\"corner2\\\":\\\"a91f98ce-f98b-b86f-5858-4a3d646ea22b\\\",\\\"wallType\\\":\\\"n\\\"},{\\\"corner1\\\":\\\"a91f98ce-f98b-b86f-5858-4a3d646ea22b\\\",\\\"corner2\\\":\\\"3c917bde-4a92-0593-7e14-3abeea730ff4\\\",\\\"wallType\\\":\\\"s\\\"},{\\\"corner1\\\":\\\"3c917bde-4a92-0593-7e14-3abeea730ff4\\\",\\\"corner2\\\":\\\"6dc7bdf0-2542-c997-a614-cdb8d952c323\\\",\\\"wallType\\\":\\\"g\\\"}],\\\"cornersOrder\\\":[[-252442.8902726021,-4533090.963113398,4465119.3403225895],[-252438.00459117617,-4533092.392307089,4465120.555984414],[-252438.27685971936,-4533099.027264776,4465113.849815241],[-252438.85690594578,-4533098.424884664,4465114.133286617],[-252438.87446771425,-4533098.852850227,4465113.700728418],[-252443.16254134322,-4533097.598074179,4465112.634159926]],\\\"roomCtrlPts\\\":[{\\\"roomName\\\":\\\"job2856&1&4&n3eky\\\",\\\"myCtrl\\\":[\\\"cb4688dd-85...,072c321f-b...\\\",\\\"6dc7bdf0...\\\"],\\\"ctrl2Pt\\\":true,\\\"materialType\\\":null,\\\"poiObjs\\\":[]}],\\\"cutoutParent\\\":null,\\\"cutoutType\\\":null}\",\"LevelNum\":1,\"tempID\":\"job2856@1@4@n3eky\"},{\"ParcelID\":\"job2856\",\"BldgNum\":\"1\",\"ComponNum\":\"5\",\"GraphicJson\":\"{\\\"groundElev\\\":284.2817687988281,\\\"hingePt\\\":null,\\\"corners\\\":{\\\"1018641d-cfff-fd9e-d412-fe75d9d2bc09\\\":{\\\"x\\\":-252432.97829072867,\\\"y\\\":-4533100.061761592,\\\"z\\\":4465112.813912762},\\\"12594dcc-490d-6190-94b0-e834b5010509\\\":{\\\"x\\\":-252433.02205957274,\\\"y\\\":-4533101.12837228,\\\"z\\\":4465111.735852042},\\\"29c99044-628a-2d59-ec7e-377e17172b1e\\\":{\\\"x\\\":-252433.64878013442,\\\"y\\\":-4533101.423264464,\\\"z\\\":4465112.053056732},\\\"272af71e-b902-8e79-4005-bd3cfae7999b\\\":{\\\"x\\\":-252433.60276756957,\\\"y\\\":-4533100.356762353,\\\"z\\\":4465113.131133937}},\\\"walls\\\":[{\\\"corner1\\\":\\\"12594dcc-490d-6190-94b0-e834b5010509\\\",\\\"corner2\\\":\\\"1018641d-cfff-fd9e-d412-fe75d9d2bc09\\\",\\\"wallType\\\":\\\"e\\\"},{\\\"corner1\\\":\\\"12594dcc-490d-6190-94b0-e834b5010509\\\",\\\"corner2\\\":\\\"29c99044-628a-2d59-ec7e-377e17172b1e\\\",\\\"wallType\\\":\\\"h\\\"},{\\\"corner1\\\":\\\"29c99044-628a-2d59-ec7e-377e17172b1e\\\",\\\"corner2\\\":\\\"272af71e-b902-8e79-4005-bd3cfae7999b\\\",\\\"wallType\\\":\\\"f\\\"},{\\\"corner1\\\":\\\"1018641d-cfff-fd9e-d412-fe75d9d2bc09\\\",\\\"corner2\\\":\\\"272af71e-b902-8e79-4005-bd3cfae7999b\\\",\\\"wallType\\\":\\\"h\\\"}],\\\"cornersOrder\\\":[[-252432.97829072867,-4533100.061761592,4465112.813912762],[-252433.02205957274,-4533101.12837228,4465111.735852042],[-252433.64878013442,-4533101.423264464,4465112.053056732],[-252433.60276756957,-4533100.356762353,4465113.131133937]],\\\"roomCtrlPts\\\":[{\\\"roomName\\\":\\\"job2856&1&5&x7t8uw\\\",\\\"myCtrl\\\":[\\\"29c99044-6...,272af7...\\\",\\\"12594dcc-490...\\\"],\\\"ctrl2Pt\\\":true,\\\"materialType\\\":null,\\\"poiObjs\\\":[]}],\\\"cutoutParent\\\":null,\\\"cutoutType\\\":null}\",\"LevelNum\":1,\"tempID\":\"job2856@1@5@x7t8uw\"},{\"ParcelID\":\"job2856\",\"BldgNum\":\"1\",\"ComponNum\":\"6\",\"GraphicJson\":\"{\\\"groundElev\\\":284.2817687988281,\\\"hingePt\\\":null,\\\"corners\\\":{\\\"12594dcc-490d-6190-94b0-e834b5010509\\\":{\\\"x\\\":-252433.02205957274,\\\"y\\\":-4533101.12837228,\\\"z\\\":4465111.735852042},\\\"53567ce9-4aa7-16b7-54e8-45b49315f120\\\":{\\\"x\\\":-252433.64517179123,\\\"y\\\":-4533101.523473014,\\\"z\\\":4465111.299505856},\\\"29c99044-628a-2d59-ec7e-377e17172b1e\\\":{\\\"x\\\":-252433.64878013442,\\\"y\\\":-4533101.423264464,\\\"z\\\":4465112.053056732}},\\\"walls\\\":[{\\\"corner1\\\":\\\"12594dcc-490d-6190-94b0-e834b5010509\\\",\\\"corner2\\\":\\\"53567ce9-4aa7-16b7-54e8-45b49315f120\\\",\\\"wallType\\\":\\\"e\\\"},{\\\"corner1\\\":\\\"53567ce9-4aa7-16b7-54e8-45b49315f120\\\",\\\"corner2\\\":\\\"29c99044-628a-2d59-ec7e-377e17172b1e\\\",\\\"wallType\\\":\\\"s\\\"},{\\\"corner1\\\":\\\"12594dcc-490d-6190-94b0-e834b5010509\\\",\\\"corner2\\\":\\\"29c99044-628a-2d59-ec7e-377e17172b1e\\\",\\\"wallType\\\":\\\"h\\\"}],\\\"cornersOrder\\\":[[-252433.02205957274,-4533101.12837228,4465111.735852042],[-252433.64517179123,-4533101.523473014,4465111.299505856],[-252433.64878013442,-4533101.423264464,4465112.053056732]],\\\"roomCtrlPts\\\":[{\\\"roomName\\\":\\\"job2856&1&6&dfroal\\\",\\\"myCtrl\\\":[\\\"12594dcc-4...,53567ce9-4aa...\\\",\\\"29c99044-628a-2d...\\\"],\\\"ctrl2Pt\\\":true,\\\"materialType\\\":null,\\\"poiObjs\\\":[]}],\\\"cutoutParent\\\":null,\\\"cutoutType\\\":null}\",\"LevelNum\":1,\"tempID\":\"job2856@1@6@dfroal\"},{\"ParcelID\":\"job2856\",\"BldgNum\":\"1\",\"ComponNum\":\"7\",\"GraphicJson\":\"{\\\"groundElev\\\":284.2817687988281,\\\"hingePt\\\":null,\\\"corners\\\":{\\\"1018641d-cfff-fd9e-d412-fe75d9d2bc09\\\":{\\\"x\\\":-252432.97829072867,\\\"y\\\":-4533100.061761592,\\\"z\\\":4465112.813912762},\\\"272af71e-b902-8e79-4005-bd3cfae7999b\\\":{\\\"x\\\":-252433.60276756957,\\\"y\\\":-4533100.356762353,\\\"z\\\":4465113.131133937},\\\"82f17acc-70e8-8ebe-e834-8b23d1b396cb\\\":{\\\"x\\\":-252433.55693677737,\\\"y\\\":-4533099.613036891,\\\"z\\\":4465113.2339232275}},\\\"walls\\\":[{\\\"corner1\\\":\\\"1018641d-cfff-fd9e-d412-fe75d9d2bc09\\\",\\\"corner2\\\":\\\"272af71e-b902-8e79-4005-bd3cfae7999b\\\",\\\"wallType\\\":\\\"h\\\"},{\\\"corner1\\\":\\\"82f17acc-70e8-8ebe-e834-8b23d1b396cb\\\",\\\"corner2\\\":\\\"272af71e-b902-8e79-4005-bd3cfae7999b\\\",\\\"wallType\\\":\\\"s\\\"},{\\\"corner1\\\":\\\"1018641d-cfff-fd9e-d412-fe75d9d2bc09\\\",\\\"corner2\\\":\\\"82f17acc-70e8-8ebe-e834-8b23d1b396cb\\\",\\\"wallType\\\":\\\"e\\\"}],\\\"cornersOrder\\\":[[-252432.97829072867,-4533100.061761592,4465112.813912762],[-252433.60276756957,-4533100.356762353,4465113.131133937],[-252433.55693677737,-4533099.613036891,4465113.2339232275]],\\\"roomCtrlPts\\\":[{\\\"roomName\\\":\\\"job2856&1&7&b2wktb\\\",\\\"myCtrl\\\":[\\\"101864...,82f17acc-70e...\\\",\\\"272af71...\\\"],\\\"ctrl2Pt\\\":true,\\\"materialType\\\":null,\\\"poiObjs\\\":[]}],\\\"cutoutParent\\\":null,\\\"cutoutType\\\":null}\",\"LevelNum\":1,\"tempID\":\"job2856@1@7@b2wktb\"}]}",
"wall_model": null,
"cropped_image": null,
"parent": null
}
share_key
[Required][type:string] Any valid share_key
string (for example, 0123a45678b9cdef0123a45678b9cdef
). A unique identifier used to access a shared job, this key is generated when a job is shared.
GET /shared-jobs/{share_key}/oblique/
HTTP method
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/shared-jobs/0123a45678b9cdef0123a45678b9cdef/oblique/?orientation=n' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
--output shared-jobs_b9cdef_oblique_orientation-n.jpg
The output is saved to a file named shared-jobs_b9cdef_oblique_orientation-n.jpg in the same directory where the cURL call was made.
share_key
[Required][type:string] Any valid share_key
string (for example, 0123a45678b9cdef0123a45678b9cdef
). A unique identifier used to access a shared job, this key is generated when a job is shared.
GET /shared-jobs/{share_key}/ortho/{layer}/{z}/{x}/{y}/
HTTP method
curl -X 'GET' \
'https://api.geospan.com/remote4d/v1/api/gpro/shared-jobs/0123a45678b9cdef0123a45678b9cdef/ortho/base/12/2048/2048/' \
-H 'Authorization: Api-Key <geospanapikeystring>' \
--output shared-jobs_8b9cdef_ortho_base-12-2048-2048.jpg
The output is saved to a file named shared-jobs_8b9cdef_ortho_base-12-2048-2048.jpg in the same directory where the cURL call was made.
Parameters
share_key
[Required][type:string] Any valid share_key
string (for example, 0123a45678b9cdef0123a45678b9cdef
). A unique identifier used to access a shared job, this key is generated when a job is shared.
Subsections of gPro & xPress
xPress Model
The GEOSPAN xPress model is designed as a subset of the existing gPro tier. No new API calls or endpoints are introduced, while others are limited in the xPress model tier. This approach simplifies integration for integrators who require fast models with the basic functionality, while maintaining compatibility with the broader gPro API.
For an overview of why and when to order an xPress model, see Introducing xPress. Here, learn how to order an xPress model, and read about the technical details and differences between the xPress model and the gPro model.
Choose the roof_model_express
product
To get an xPress model, use the products
value roof_model_express
when creating an order.
Check in real time for gPro API support of the xPress model: when you have ordered the roof_model_express
product, any gPro API that does not support the xPress product—for example model sharing—returns a 415
.
The gPro overview has a dropdown in the upper right corner of the screen that toggles between gPro and xPress models for easy filtering.
The same endpoints and underlying infrastructure mean you can easily transition to the full gPro tier without additional integration, as the foundational API structure and calls remain consistent.
What’s different in the xPress model?
- Order the xPress model: Use
roof_model_express
for yourproducts
value when you make a call to the/order
API to get faster computations and reduced processing costs without sacrificing accuracy for basic requirements. - DOCX-Only file export: xPress exports only the DOCX format.
- No Job sharing support: You cannot share the xPress model through the API or the Geospan gSuite user interface.
- 2D-Only structure coordinates: Structure coordinates in the xPress API are flattened to 2D, optimizing data processing and storage for applications that do not require 3D representations.
API Specification
Before getting started
Before starting with the gPro API, take time to review Get Started and familiarize yourself with the Concepts.
Working with Webhooks
Webhooks allow real-time notifications of events occurring in the GEOSPAN system. They are enabled on a per-account basis and can be configured to send notifications for various events related to orders and jobs.
Webhooks need to be enabled by a GEOSPAN admin. Please contact your GEOSPAN sales representative to have them enabled.
GEOSPAN Webhooks Workflow
The following workflow shows how to enable webhooks. Work with your GEOSPAN sales rep on this early release of webhooks.
Webhook events are configured and triggered on an account-wide basis, rather than a per-user basis. When a webhook is set up, it listens for and returns events for all users associated with that account, not just the user who configured the webhook.
This allows for centralized event handling across your entire organization’s GEOSPAN activities, as the webhook returns events for all users under the account, regardless of which user originally set up the webhook.
- Enable Webhooks with your GEOSPAN sales rep:
- Contact your GEOSPAN sales rep to enable webhooks.
- Provide your callback URL, desired events (e.g.,
orderCreated
,jobCompleted
), and optional custom header for security.
- Prepare Your Server:
- Set up an endpoint to receive POST requests at the callback URL.
- Implement logic to handle and process webhook payloads.
- Secure Your Endpoint:
- Validate the custom header if provided.
- Implement error handling and logging.
- Process Webhook Events:
- Parse JSON payloads.
- Handle each event type (e.g.,
orderCreated
,jobCompleted
) with specific logic.
- Test and Monitor:
- Work with GEOSPAN to test the integration.
- Set up monitoring and error alerts.
- Scale and Optimize:
- Ensure handling can scale with event volume.
- Implement retry logic or queueing if needed.
- Maintain and Update:
- Stay in touch with GEOSPAN for updates.
- Adjust handling for new event types as needed.
Available Events
orderCreated
Triggered each time an order is created on the account.
Example event:
{
"eventType": "orderCreated",
"target": {
"order": 100999,
"jobs": [
123,
456,
]
}
}
orderCompleted
Triggered each time an order is completed for the account.
Example event:
{
"eventType": "orderCompleted",
"target": {
"order": 100999,
"jobs": [
123,
456,
]
}
}
orderCanceled
Triggered each time an order is canceled on the account. This means that all jobs on the order have been canceled as well.
Example event:
{
"eventType": "orderCanceled",
"target": {
"order": 100999,
"jobs": [
123,
456,
]
}
}
jobCompleted
Triggered when an individual job on an order has been completed.
Example event:
{
"eventType": "jobCompleted",
"target": {
"order": 100999,
"jobs": [
123
]
}
}
jobCanceled
Triggered when an individual job on an order has been completed.
Example event:
{
"eventType": "jobCanceled",
"target": {
"order": 100999,
"jobs": [
123
]
}
}
exportReady
Triggered when a file type (e.g., dxf
, xml
) for an order has finished exporting.
Example event:
{
"eventType": "exportReady",
"target": {
"order": 100999,
"jobs": [
123
]
}
}
Introducing xPress
The GEOSPAN xPress API tier is for businesses and developers who need reliable roof assessments with speed, efficiency, and cost-effectiveness. This tier offers streamlined functionality while maintaining the essential features needed to handle orders effectively, such as overhead and oblique images, line drawings, measurement outputs, pitch detection, and total area calculations.
Order an xPress model and use the same gPro API. For the technical details on how to order an xPress model, see xPress Model.
Why choose xPress API?
The xPress API maximizes efficiency without compromising on essential capabilities.
- Speed: Reduced complexity in models and data formats.
- Cost-Efficiency: Streamlined features translate to lower operational costs.
- Simplicity: Focuses on essential features that drive progress.
What’s different in the xPress model?
While gPro includes additional features (such as advanced roof features, 3D modeling, and insurance format support), gPro Xpress streamlines the process for quicker results with a focus on accuracy and efficiency, making it a great choice for users who need a rapid yet detailed analysis.
The xPress model offers a streamlined roofing calculation service through the /order
API endpoint, providing faster processing at reduced costs while maintaining accuracy for basic needs. It exports exclusively to DOCX format and operates with 2D structure coordinates rather than 3D representations. The model does not support job sharing functionality either through the API or the Geospan gSuite interface.
When to choose xPress API
The xPress API tier is a streamlined, cost-effective solution for specific use cases. It offers simplified functionality, faster processing, and reduced data complexity, making it a practical choice for focused applications, such as retail roofing.
xPress is particularly suited for use cases where simplicity and rapid processing are key. xPress is not suitable for use cases that require high-accuracy confidences, such as insurance workflows that may require 95-99% accuracy. Below are scenarios where the xPress API tier is the best fit.
1. Simplified data models
- When you need: quick, lightweight models for single-property assessments or simplified mapping applications.
- Uses
roof_model_express
: Ideal for projects that require basic modeling without the computational overhead of more complex models. - 2D Coordinates: If your application doesn’t require 3D structural data, the xPress API’s flattened 2D structure coordinates provide a straightforward solution that simplifies integration and data handling.
2. The DOCX file format
-
When you need: measurements in a standard business format.
Supports export calls only to the DOCX format, a widely used document type.
3. No job sharing
-
When you need: automated order pipelines or systems with a single job or user account per process.
The xPress API does not support job sharing, making it ideal for single-user operations or environments where collaboration features are unnecessary. Reduces potential complexities in API calls and simplifies security management.
4. Prioritizing speed and cost efficiency
-
When you need: Batch-processed orders with minimal overhead.
This makes it a great choice for high-volume, cost-sensitive applications.
Try the xPress model today
Read the xPress Model overview. Then review gPro & xPress Models APIs with the model toggle set to “xPress”.
Spatial
Geospan’s Spatial APIs provide Geographic Information System (GIS) functionality that integrates with GEOSPAN services. These geospatial helper APIs are useful to assist with both gSquare and gPro applications.
The Spatial APIs allow you to retrieve spatial data, such as roof footprints, within a specified bounding box. Use these APIs, combined with data from other Geospan API, to analyze and visualize geospatial information.
Authentication
Authentication for the Spatial APIs uses the same API-Key
as the gPro API. Include your API key in the Authorization
header of your requests:
Authorization: Api-Key YOUR_API_KEY
Base URL
The base URL for the Spatial APIs is:
https://api.geospan.com/remote4d/v1/api/spatial/
Using the Spatial APIs with gPro Data
One way to use the Spatial APIs in conjunction with the gPro APIs is by:
- Retrieving GeoJSON data for a specific job from the gPro API
- Calculating a bounding box based on the coordinates in the GeoJSON data
- Using the calculated bounding box to query the Spatial API for footprints data
By following this process, you can combine the detailed structure information from the gPro APIs with the broader spatial context provided by the Spatial APIs.
Review the following Python and JavaScript examples to see gSquare in action.
Review and download example code
The API keys and tokens in index.js are for demonstration only. In a real application, secure them using appropriate methods, such as environment variables, backend proxies, and IAM services with temporary credentials.
// Footprints API interaction script for browser environments
// Function to create and append a pre element with the given content
function appendPre(content, parent = document.getElementById('results')) {
const pre = document.createElement('pre');
pre.textContent = JSON.stringify(content, null, 2);
parent.appendChild(pre);
}
// Main function to execute the API call
async function fetchFootprints(apiKey) {
if (!apiKey) {
console.error("API key is required");
appendPre("Error: API key is required");
return;
}
// Hardcoded bounding box coordinates
const minLon = -93.18814705349445;
const minLat = 44.71487409726919;
const maxLon = -93.18663294650553;
const maxLat = 44.715445901318304;
const bounds = `${minLon},${minLat},${maxLon},${maxLat}`;
// Query the Spatial API using the hardcoded bounding box
const url = 'https://api.geospan.com/remote4d/v1/api/spatial/footprints';
const params = new URLSearchParams({ bounds });
const headers = {
'Authorization': `Api-Key ${apiKey}`,
'accept': 'application/json'
};
try {
const response = await fetch(`${url}?${params}`, { headers });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const footprintsData = await response.json();
console.log("Footprints data:", footprintsData);
appendPre("Footprints data:");
appendPre(footprintsData);
} catch (error) {
console.error("An error occurred:", error);
appendPre(`An error occurred: ${error.message}`);
}
}
// Set up event listener for form submission
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('apiKeyForm');
const resultsDiv = document.getElementById('results');
form.addEventListener('submit', (e) => {
e.preventDefault();
resultsDiv.innerHTML = ''; // Clear previous results
const apiKey = document.getElementById('apiKey').value;
fetchFootprints(apiKey);
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Footprints API Demo</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
h1 {
color: #333;
}
form {
margin-bottom: 20px;
}
input[type="text"] {
width: 300px;
padding: 5px;
}
button {
padding: 5px 10px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
pre {
background-color: #f4f4f4;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
white-space: pre-wrap;
word-wrap: break-word;
}
</style>
</head>
<body>
<h1>Footprints API Demo</h1>
<form id="apiKeyForm">
<label for="apiKey">Enter your API Key:</label>
<input type="text" id="apiKey" name="apiKey" required>
<button type="submit">Fetch Footprints</button>
</form>
<div id="results"></div>
<script src="index.js"></script>
</body>
</html>
"""
Get GeoJSON from gPro API and query the Spatial API using a calculated bounding box
"""
import requests
import json
import os
import sys
GEOSPAN_API_KEY = os.getenv("GEOSPAN_API_KEY") or input("Please enter your API key: ")
API_HOME = os.getenv("GEOSPAN_API_HOME", "https://api.geospan.com/remote4d/v1/api/")
# Define the run_example function
def run_example(silent=False):
min_lon, min_lat, max_lon, max_lat = [
-93.18814705349445,
44.71487409726919,
-93.18663294650553,
44.715445901318304,
]
bounds = f"{min_lon},{min_lat},{max_lon},{max_lat}"
# Step 3: Query the Spatial API using the calculated bounding box
url = f"{API_HOME}/spatial/footprints"
params = {"bounds": bounds}
headers = {
"Authorization": f"Api-Key {GEOSPAN_API_KEY}",
}
response = requests.get(url, params=params, headers=headers)
response.raise_for_status()
footprints_data = response.json()
if not silent:
# Output the footprints data
print("Footprints data:")
print(json.dumps(footprints_data, indent=2))
return 0 # Return 0 to indicate success
if __name__ == "__main__":
if not GEOSPAN_API_KEY:
print("API key is required.")
sys.exit(1) # Exit with non-zero exit code for failure
sys.exit(run_example())
Subsections of Spatial
API Specification
Before starting with the Spatial API, take time to review Get Started and familiarize yourself with the Concepts.
Concepts
After you have reviewed the steps to Get Started with GEOSPAN, review the following topics to become familiar with geospatial and geoprocessing topics within the GEOSPAN ecosystem.
Well-Known-Text (WKT)
What is WKT?
WKT is a simplified geometry encoding that is quick to parse and emit. The Wikipedia page for WKT has a nice write-up and examples of the format in use.
Why not GeoJSON?
GeoJSON is great! But there are some advantages that WKT can provide:
- Typing for WKT is much simpler. GeoJSON is an object-type with very specific property values and sub-objects. While this can be done it requires additional overhead and the type (
object
) on initial glance is not descriptive. WKT is a string. The input property is namedwkt
in GEOSPAN APIs to provide consistency and clarity that this is a WKT-String and those familiar with common GIS geometry-types will recognize it immediately. - WKT parsing can be deferred. When embedding a GeoJSON object into a request body, the entire body of the request, including the GeoJSON will be parsed by most frameworks. If an API does not actually need the geometry information this can slow down request parsing especially as the GeoJSON grows larger in size.
Helpful utilities for WKT
- OpenLayer’s ol/format/WKT will parse and emit WKT.
- MapBox’s wellknown will parse WKT and emit GeoJSON.
- Shapely supports loading and dumping in WKT
WGS84 Decimal Degrees
GEOSPAN APIs expect incoming geometries to use WGS84 Decimal Degrees. This is the same as the GeoJSON specification.
gSquare Lifecycle
Estimates are generated asynchronously. A request is made to create an estimate, a query key is returned, and then the query should be monitored for success or failure.
flowchart LR A[Call /estimate/] -->|Get queryKey| B(Poll /query/:queryKey) B --> C{Check status} C -->|PENDING| C C -->|FAILURE| E[Report error] C -->|SUCCESS| F[Read results]
gPro Lifecycle
Requests for the gPro API go through a multi-stage lifecycle. A new request can either enter the “Pre-Model” stage or be immediately canceled. From “Pre-Model”, the request moves to “Ready” and then “Modeling”. During “Modeling”, the request goes through a series of QA steps, during which the request can be progressed, rejected, or canceled. The final outcome is either the request being completed or rejected.
flowchart TD A[New] --> B[Pre-Model] A[New] --> N((Canceled)) B[Pre-Model] --> C[Ready] B[Pre-Model] --> N((Canceled)) C[Ready] --> D[Modeling] D[Modeling] --> E[QA1] E[QA1] --> F[QA1 In Process] E[QA1] --> I[Rejected] E[QA1] --> N((Canceled)) F[QA1 In Process] --> G[QA2] F[QA1 In Process] --> I[Rejected] F[QA1 In Process] --> N((Canceled)) G[QA2] --> H[QA2 In Process] G[QA2] --> J[Failed QA] G[QA2] --> I[Rejected] H[QA2 In Process] ----> L((Completed)) H[QA2 In Process] --> J[Failed QA] H[QA2 In Process] --> N((Canceled)) H[QA2 In Process] --> G[QA2] I[Rejected] --> D[Modeling] I[Rejected] --> N((Canceled)) J[Failed QA] --> F[QA1 In Process] J[Failed QA] --> I[Rejected] J[Failed QA] --> N((Canceled)) style L fill:#6fac5d style N fill:#b94663 style F fill:#bc7d39 style H fill:#bc7d39 style D fill:#bc7d39 style B fill:#bc7d39