Skip to main content
Version: 1.7.3.X

Routing

Route helpers let you manage saved multi-stop routes inside a map control. A route can include a name, waypoint list, route color, transport mode, waypoint optimization, and avoid preferences.

Why you'd use these helpers​

  • Save repeatable route plans for dispatch, inspections, or service runs.
  • Update a route definition when stops or constraints change.
  • Quickly navigate the map to a selected route context.
  • Keep route behavior predictable by explicitly setting transport, optimize, and avoid options.

Usage pattern​

const control = globalThis.MaptaskrControlManager.getControl(controlId);

All examples below assume you already have a valid control reference.

Types​

export interface RouteWaypoint {
name: string;
lng: number;
lat: number;
}

export interface RouteAvoidOptions {
motorways?: boolean;
tollRoads?: boolean;
ferries?: boolean;
}

export type RouteScope = 'MyRoute' | 'RecordRoute' | 'MapRoute' | 'MapRouteByCode';

export interface CustomRoute {
routeId?: string;
routeName: string;
waypoints: RouteWaypoint[];
routeColor?: string;
transportationMethod?: 'car' | 'truck' | 'walk';
optimize?: boolean;
avoid?: RouteAvoidOptions;
scope?: RouteScope;
select?: boolean;
}

API reference​

getRoutes​

List all currently available routes for the current map context.

Parameters: None

Returns: CustomRoute[]

Usage:

const routes = control.getRoutes();

routes.forEach((route) => {
console.log(`${route.routeName} (${route.routeId})`, route.waypoints.length);
});

Example response:

[
{
routeId: 'eb00c94d-1459-41ad-95c6-d112967717e6',
routeName: 'New Route 2',
scope: 'MyRoute',
transportationMethod: 'car',
routeColor: 'rgb(0, 230, 52)',
optimize: false,
avoid: { motorways: false, tollRoads: false, ferries: true },
waypoints: [
{ name: 'test3', lng: 115.9086, lat: -31.9753 },
{ name: 'Test Account 1', lng: 115.83754, lat: -32.11547 },
],
},
];
info

Some optional fields may be omitted if they were not set when the route was created.

addOrUpdateRoute​

Create a new route or update an existing route by ID.

When updating, pass the existing routeId and the full route payload you want saved.

Authentication and update permissions​

An authenticated user is required to create or update routes. Anonymous users cannot use this operation.

For non-record routes, the creator can edit the route; admins can also edit other users' MapRoute and MapRouteByCode routes. RecordRoute routes are collaborative: authenticated users can edit them within the matching record context.

An existing route must belong to the current map configuration. For an existing RecordRoute, its record ID, entity type, and field name must match the map's currentEntityId, currentEntityType, and currentEntityFieldName. This applies even when making the route private, and admins cannot bypass the context checks. Updating a record route preserves its association rather than rebinding it to another record.

These checks also apply when a supplied routeId identifies a saved route that is not already loaded in the map.

Parameters:

FieldTypeRequiredDescription
routeIdstringNoIf provided, updates that route. If omitted/empty, creates a new route.
routeNamestringYesDisplay name for the route.
waypointsRouteWaypoint[]YesOrdered waypoint list (maximum 150).
routeColorstringNoRoute color, for example rgb(0, 230, 52).
transportationMethod'car' | 'truck' | 'walk'NoRouting mode to use.
optimizebooleanNoEnables/disables waypoint optimization.
avoidRouteAvoidOptionsNoOptional avoid flags: motorways, tollRoads, ferries.
scopeRouteScopeNoDefaults to MyRoute for a new route. If omitted on update, preserves the existing scope.
selectbooleanNoSelects/highlights the route after recalculation. Defaults to false.

Returns: Promise<void>. Read the saved route with getRoutes() after awaiting the operation. Returned routes include their scope; shared is not a public input or output field.

Route scope​

ScopeVisibility
MyRouteA private personal route in My Routes.
RecordRouteA shared route associated with the current record, in Record Routes.
MapRouteA shared route for the current map configuration, in Map Routes.
MapRouteByCodeA shared route in Map Routes, visible to its owner. Other users must add its route code before it appears in their list.

Sharing is determined by scope. To change an existing route's scope, pass its routeId and the new scope. When permitted, setting MyRoute makes it private; setting any other scope makes it shared subject to that scope's visibility rules.

Creating a RecordRoute, or changing another scope to RecordRoute, requires nonblank values for the map's current record ID, entity type, and field name (currentEntityId, currentEntityType, and currentEntityFieldName). The route is associated with that record and field.

Sharing permissions​

Changing sharing requires edit permission and the route's share or unshare permission. The following mapFeatureConfig settings also apply when sharing, unsharing, or changing between shared scopes:

SettingDefaultRequirement
canShareRoutestrueMust be enabled for any sharing change, including making a shared route private.
onlyAdminCanShareRoutesfalseWhen enabled, only admins can change sharing.
allowShareRoutesByCodetrueMust be enabled for MapRouteByCode, even for admins. When disabled, non-admins cannot change sharing for any scope.

Creating or changing to MapRoute also requires an admin. Admins can use MapRoute when code sharing is disabled, provided the other sharing checks pass.

Permitted edits that retain the existing scope and sharing state do not require sharing to be enabled.

Errors​

ErrorCause
Route changes require an authenticated userThe current user ID is missing, blank, or anon (case-insensitive).
Cannot update a route outside the current map or record contextThe existing route belongs to another map configuration, or its record context does not match the current record and field.
addOrUpdateRoute requires a valid route scopeThe supplied scope is not one of the four supported values.
Record routes require a current record id, entity type, and field nameCreating or changing to RecordRoute without all three nonblank record-context values.
You do not have permission to edit this routeThe caller does not have edit permission for the route.
Route sharing is not permitted for the requested scopeA sharing change is blocked by route permissions, map settings, or scope-specific admin requirements.

Usage - create a route:

const waypoints = [
{ name: 'Depot', lng: 115.9086, lat: -31.9753 },
{ name: 'Test Account 1', lng: 115.83754, lat: -32.11547 },
];

await control.addOrUpdateRoute({
routeName: 'Adding a new route',
waypoints,
routeColor: 'rgb(0, 230, 52)',
transportationMethod: 'car',
optimize: false,
avoid: {
motorways: false,
tollRoads: false,
ferries: true,
},
});

Usage - update an existing route:

const routes = control.getRoutes();
const existing = routes.find((r) => r.routeName === 'Adding a new route');

if (existing?.routeId) {
await control.addOrUpdateRoute({
routeId: existing.routeId,
routeName: 'Adding a new route (Updated)',
waypoints: existing.waypoints,
routeColor: existing.routeColor,
transportationMethod: existing.transportationMethod,
optimize: existing.optimize,
avoid: existing.avoid,
});
}

Create or update a route by scope​

This example reuses one route ID per scope so repeated calls update the same route. To run all four calls, use an authenticated admin with route sharing and code sharing enabled, and nonblank current record ID, entity type, and field name for RecordRoute. Non-admins can use the permitted scopes individually; the MapRoute call requires an admin.

const routeIds = {};

async function addOrUpdateRouteByScope(scope = 'MyRoute') {
const validScopes = ['MyRoute', 'RecordRoute', 'MapRoute', 'MapRouteByCode'];
if (!validScopes.includes(scope)) {
throw new Error('Invalid route scope: ' + scope);
}

const routeId = routeIds[scope] || (routeIds[scope] = globalThis.crypto.randomUUID());

await control.addOrUpdateRoute({
routeId,
routeName: 'Custom code test - ' + scope,
scope,
select: true,
waypoints: [
{ name: 'Elizabeth Quay', lat: -31.958, lng: 115.857 },
{ name: 'Perth Station', lat: -31.9518, lng: 115.8603 },
{ name: 'Hyde Park', lat: -31.9368, lng: 115.862 },
],
});

const savedRoute = control.getRoutes().find((route) => route.routeId === routeId);
console.log('Route test:', savedRoute || { routeId, scope });
return { routeId, route: savedRoute };
}

await addOrUpdateRouteByScope('MyRoute');
await addOrUpdateRouteByScope('RecordRoute');
await addOrUpdateRouteByScope('MapRoute');
await addOrUpdateRouteByScope('MapRouteByCode');

deleteRoute​

Deletes a single route by its route ID.

Parameters:

FieldTypeRequiredDescription
routeIdstringYesRoute ID of the route to remove.

Returns: Promise<void>

Usage:

const routes = control.getRoutes();

const routeId = routes[0].routeId;

await control.deleteRoute(routeId);

Navigate the map view to a saved route by ID.

Parameters:

FieldTypeRequiredDescription
routeIdstringYesRoute ID to navigate to.

Returns: Promise<void>

Usage:

const routes = control.getRoutes();
const target = routes.find((r) => r.routeName === 'Adding a new route (Updated)');

if (target?.routeId) {
await control.navigateToRoute(target.routeId);
console.log('Navigated to route:', target.routeName);
}

Common workflows​

Save or refresh a daily dispatch route​

const routes = control.getRoutes();
const existing = routes.find((r) => r.routeName === 'Daily Dispatch');
const routeId = existing?.routeId || globalThis.crypto.randomUUID();

await control.addOrUpdateRoute({
routeId,
routeName: 'Daily Dispatch',
waypoints: [
{ name: 'Depot', lng: 115.9086, lat: -31.9753 },
{ name: 'Client A', lng: 115.83754, lat: -32.11547 },
{ name: 'Client B', lng: 115.7921, lat: -32.0522 },
],
transportationMethod: 'truck',
optimize: true,
avoid: { tollRoads: true },
});

const saved = control.getRoutes().find((route) => route.routeId === routeId);
console.log('Saved route:', saved);
async function navigateRouteByName(name) {
const routes = control.getRoutes();
const match = routes.find((r) => r.routeName === name);

if (!match?.routeId) {
console.warn(`Route not found: ${name}`);
return;
}

await control.navigateToRoute(match.routeId);
}

await navigateRouteByName('Daily Dispatch');

Delete a temporary route​

const routes = control.getRoutes();
const temp = routes.find((r) => r.routeName === 'Temporary Route');

if (temp?.routeId) {
await control.deleteRoute(temp.routeId);
console.log('Deleted route:', temp.routeName);
}

Best practices​

  • Keep the routeId you supply, or read it with getRoutes() after create, so updates and navigation are reliable.
  • Keep waypoint order explicit unless optimize is intentionally enabled.
  • Set transportationMethod and avoid options deliberately to prevent unexpected route behavior.
  • Use clear route naming conventions (for example team, shift, or workflow prefixes).
  • Wrap async route operations in your own error handling when wiring them to UI actions or automations.