Map Provider Integrations for Field Service Management: Configure Third-Party Map Providers<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } Introduction The Field Service Management (FSM) plugins provide built-in integrations with Google Maps and Beans.ai, and are also designed to support additional third-party map providers. This document covers how to configure and use these map provider integrations, as well as how to onboard new providers into the system. It also describes how map providers can be leveraged within key FSM capabilities such as dynamic scheduling and schedule optimization. Set up Existing Map Provider Integrations FSM integrates with Google Maps and Beans.ai to power features like dynamic scheduling and schedule optimization. Follow the steps below to configure connections with either provider. Set up Google Maps Connection Navigate to IntegrationHub > Connections & Credentials > Connection & Credential Aliases.Open the record named Google.Click Create New Connection & Credential from the related links to create a connection with the map provider. Set up Beans.ai Connection Navigate to IntegrationHub > Connections & Credentials > Connection & Credential Aliases.Open the record named Beans.ai.Click Create New Connection & Credential from the related links to create a connection with the map provider. Test Beans.ai Connection Navigate to Process Automation > Flow Designer > Actions.Open the flow action named Look Up Matrix with application Beans.ai Spoke.Test the flow action with the required inputs as shown in the screenshot below.The action should execute without errors, and the Rows variable in the output data should contain time and distance data. The Google Maps and Beans.ai integrations will work with the FSM flows once the connections are established. Understanding Map Provider Integrations Implementation Flow Designer Spokes FSM uses two types of requests — synchronous and asynchronous — to communicate with the map providers. Synchronous: The POST action sends a request and waits for a response containing location and time data. No GET action is needed.Asynchronous: The POST action sends a request and receives only an acknowledgement with a request_id. A separate GET action is used later to retrieve the location and time data using the same request_id. A POST action is required if the map provider supports synchronous requests, and both POST and GET spokes are required for asynchronous requests. Scripted Extension Implementations The processRequest function in FSMMapProviderHelper script include orchestrates all communication with the map provider. Please refer to the FSMMapProviderHelper and FSMBeansImpl script includes for reference. The following steps are executed in order: Validate input — The function validates the input structure. An error is thrown if it does not match the expected format. Here is the JSON format of the request object sent to the function. { "locations": [ { "lat": 43.6918413, "lon": -78.3485228 }, { "lat": 43.6425662, "lon": -78.3870568 } ], "vendor": "beans", "callType": "sync", "requestType": "POST", "requestId": "unique_matrixId", "matrixField": "optimizedTravelTimeDistances", "includeResponseMetaData": true } Find implementation class — Uses the scripted extension point sn_fsm_map_integr.FSMMapProviderImpl to find a script include whose handles function returns true for the given map provider. An error is thrown if no matching implementation is found.Transform request — Calls transformRequest function from the implementation class to convert the request into the structure expected by the Flow Designer spoke. If not defined, the request is passed through as-is.Call the provider — Calls processRequest from the implementation class to query the map provider API and return the response. An error is thrown if this function is not defined.Validate response (optional) — Calls validateResponse from the implementation class to validate the spoke's response. If not defined, the response is treated as valid.Transform response — Calls transformResponse from the implementation class to reshape the response. If not defined, the response is returned as-is.Validate output — The final response is evaluated against the expected output structure. An error is thrown if it does not match. Here is the expected JSON format of the response object. { "matrix": { "optimizedTravelTimeDistances": [], "numOrigins": 2, "numDestinations": 2, "durations": [0, 163.8, 163.8, 0], "distances": [0, 2162.5, 2162.5, 0], "numLocations": 2 }, "vendor": "beans", "matrixId": "unique_matrixId" } Integrate a New Map Provider Set up Connection with the New Map Provider Navigate to IntegrationHub > Connections & Credentials > Connection & Credential Aliases.Click New to create a new record.Fill in the necessary details and submit the form.Fill in the Configuration Template field and create the connection by clicking Create New Connection & Credential from the related links. Add the Map Provider to the Travel Time Estimate Configuration table Navigate to Map Integrations for Field Service > Travel Time Estimate Configuration > All.Right-click on the table and select Configure > Table.Open the column Travel estimate provider.Add the new map provider to the list of choices.Create a new record in the table with the Travel estimate provider as the new map provider. Make sure to populate the appropriate name for the record.Here is an example screenshot for a new map provider named 'New Provider'. Create a Flow Designer Spoke for the POST request Navigate to Process Automation > Flow Designer > Actions and create a new flow designer action.Create the inputs as required, and an output for the data returned by the map provider API.The action should take inputs, query your map provider's API, and return the response as output.The request payload must include a request_id to uniquely identify the request.For synchronous requests, the response must include the time-distance matrix.For asynchronous requests, the response does not need to include this data, but must return the request_id. Create a Flow Designer Spoke for the GET request Navigate to Process Automation > Flow Designer > Actions and create a new flow designer action.Create the inputs as required, and an output for the data returned by the map provider API.The action should take request_id as input, query your map provider's API, and return the response as output.The response should contain the location and time data associated with the original POST request. Configure the FSM Map Provider Policy Decision Table Navigate to Map Integrations for Field Service > Map Provider Configuration.Add your provider as a new choice option in the Map Vendor input.Create new decision rows for your provider to return the Flow Designer spokes for sync and async call types, using the connection alias, POST Action, and GET Action created earlier.If your provider supports synchronous requests, create one decision row with the POST spoke.If your provider supports asynchronous requests, create two decision rows with both POST and GET spokes.Test the decision table using the Test button at the top.Here are example screenshots of the decision table for a new map provider named 'New Provider'. Create a Valid Scripted Extension Implementation Create a new script include that implements the sn_fsm_map_integr.FSMMapProviderImpl extension point for your map provider. Use the FSMBeansImpl script include as a reference implementation. The script include must define the following functions: handles(mapProvider) — Returns true if mapProvider matches the choice value added in the previous step. Here is a sample implementation for the map provider created in the above step. transformRequest(request) — Transforms the input request object into the structure expected by your Flow Designer spoke. The input follows this structure: { "locations": [ { "lat": 43.6918413, "lon": -78.3485228 }, { "lat": 43.6425662, "lon": -78.3870568 } ], "vendor": "beans", "callType": "sync", "requestType": "POST", "requestId": "unique_id", "matrixField": "optimizedTravelTimeDistances", "includeResponseMetaData": true } processRequest(transformedRequest) — Calls the Flow Designer spoke and returns the response. Here is a sample implementation of this function. validateResponse(response) (optional) — Validates the response returned by the spoke.transformResponse(response) — Transforms the spoke response into the expected output format: { "matrix": { "optimizedTravelTimeDistances": [], "numOrigins": 2, "numDestinations": 2, "durations": [0, 163.8, 163.8, 0], "distances": [0, 2162.5, 2162.5, 0], "numLocations": 2 }, "vendor": "beans", "matrixId": "unique_id" } Test the Implementation Navigate to System Web Services > GraphQL Explorer and execute the following queries. They should return data without errors. Replace the vendor value with the new provider created in the above steps. { snFsmMapIntegr { travelTime { getTravelTimeDistanceEstimates( requestPayload: { locations: [ { lat: 43.6918413, lon: -79.3485228 } { lat: 43.6425662, lon: -79.3870568 } ] vendor: "beans" callType: sync } ) { ... on snFsmMapIntegr_travelTime_Success { result { matrixId matrix { numLocations durations distances } } } ... on snFsmMapIntegr_travelTime_Failure { errorType errorMessage } } } } } { snFsmMapIntegr { travelTime { getTravelTimeDistanceEstimates( requestPayload: { matrixId: "unique_matrixId" locations: [ { lat: 43.6918413, lon: -79.3485228 } { lat: 43.6425662, lon: -79.3870568 } ] vendor: "beans" callType: async } ) { ... on snFsmMapIntegr_travelTime_Success { result { matrixId matrix { numLocations durations distances } } } ... on snFsmMapIntegr_travelTime_Failure { errorType errorMessage } } } } } { snFsmMapIntegr { travelTime { getTravelTimeDistanceEstimatesWithMatrixId( matrixId: { matrixId: "unique_matrixId", vendor: "beans" } ) { ... on snFsmMapIntegr_travelTime_Success { result { matrixId matrix { numLocations durations distances } } } ... on snFsmMapIntegr_travelTime_Failure { errorType errorMessage } } } } }