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 },
],
},
];
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:
| Field | Type | Required | Description |
|---|---|---|---|
routeId | string | No | If provided, updates that route. If omitted/empty, creates a new route. |
routeName | string | Yes | Display name for the route. |
waypoints | RouteWaypoint[] | Yes | Ordered waypoint list (maximum 150). |
routeColor | string | No | Route color, for example rgb(0, 230, 52). |
transportationMethod | 'car' | 'truck' | 'walk' | No | Routing mode to use. |
optimize | boolean | No | Enables/disables waypoint optimization. |
avoid | RouteAvoidOptions | No | Optional avoid flags: motorways, tollRoads, ferries. |
scope | RouteScope | No | Defaults to MyRoute for a new route. If omitted on update, preserves the existing scope. |
select | boolean | No | Selects/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
| Scope | Visibility |
|---|---|
MyRoute | A private personal route in My Routes. |
RecordRoute | A shared route associated with the current record, in Record Routes. |
MapRoute | A shared route for the current map configuration, in Map Routes. |
MapRouteByCode | A 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:
| Setting | Default | Requirement |
|---|---|---|
canShareRoutes | true | Must be enabled for any sharing change, including making a shared route private. |
onlyAdminCanShareRoutes | false | When enabled, only admins can change sharing. |
allowShareRoutesByCode | true | Must 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
| Error | Cause |
|---|---|
Route changes require an authenticated user | The current user ID is missing, blank, or anon (case-insensitive). |
Cannot update a route outside the current map or record context | The existing route belongs to another map configuration, or its record context does not match the current record and field. |
addOrUpdateRoute requires a valid route scope | The supplied scope is not one of the four supported values. |
Record routes require a current record id, entity type, and field name | Creating or changing to RecordRoute without all three nonblank record-context values. |
You do not have permission to edit this route | The caller does not have edit permission for the route. |
Route sharing is not permitted for the requested scope | A 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:
| Field | Type | Required | Description |
|---|---|---|---|
| routeId | string | Yes | Route ID of the route to remove. |
Returns: Promise<void>
Usage:
const routes = control.getRoutes();
const routeId = routes[0].routeId;
await control.deleteRoute(routeId);
navigateToRoute
Navigate the map view to a saved route by ID.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| routeId | string | Yes | Route 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);
Navigate to route by name
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
routeIdyou supply, or read it withgetRoutes()after create, so updates and navigation are reliable. - Keep waypoint order explicit unless
optimizeis intentionally enabled. - Set
transportationMethodandavoidoptions 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.