Missions & Routes
Organise field work into Missions scoped to a store, then group them into ordered Routes for reps to execute. Together they model every type of visit schedule — from a single ad-hoc drop to a full Salesforce-pulled distribution run.
Concepts
A Mission is a unit of field work scoped to a single location. It carries the scope of the work (which tracked objects, areas, or assets to check), an optional assignee, scheduling info, and a lifecycle status that advances as the rep works through the visit.
A Route groups one or more missions into an ordered plan for a single rep. The Route has a source that records how it was created (salesforce, platform, or adhoc), an optional assignee, and its own status that reflects the collective progress of its missions.
Route ──┬── Mission (stop 1, location A)
├── Mission (stop 2, location B)
└── Mission (stop 3, location C)
Endpoints
/v1/tenants/{tenantId}/missionsCreate a mission for a location/v1/tenants/{tenantId}/missionsList missions with optional filters/v1/tenants/{tenantId}/missions/{id}Get a single mission/v1/tenants/{tenantId}/missions/{id}Advance mission status or reassign/v1/tenants/{tenantId}/routesCreate a route (with optional stops)/v1/tenants/{tenantId}/routesList routes with optional filters/v1/tenants/{tenantId}/routes/{id}Get a single route (includes missions)/v1/tenants/{tenantId}/routes/{id}Update route status, assignee, or nameCreating a mission
const mission = await tenant.missions.create({
locationId: 'loc_abc123',
assigneeId: 'usr_rep01',
scopeType: 'tracked_objects',
scopeIds: ['sku_beer_001', 'sku_beer_002'],
partial: false,
notes: 'Check facings on bottom shelf only',
scheduledAt: '2026-07-25T08:00:00Z',
});
console.log(mission.id); // "mis_xyz789"
console.log(mission.status); // "PLANNED"Listing and filtering missions
// My open missions
const myMissions = await tenant.missions.list({ mine: true, status: 'PLANNED' });
// All missions for a specific rep
const repMissions = await tenant.missions.list({ assigneeId: 'usr_rep01' });
// Missions that belong to a route
const routeMissions = await tenant.missions.list({ routeId: 'rte_abc123' });Advancing mission status
Missions follow a forward-only lifecycle: PLANNED → IN_PROGRESS → SUBMITTED → APPROVED | REJECTED.
// Rep starts the visit
await tenant.missions.updateStatus(mission.id, { status: 'IN_PROGRESS' });
// Rep submits after capturing observations
await tenant.missions.updateStatus(mission.id, { status: 'SUBMITTED' });
// Supervisor approves with an optional review note
await tenant.missions.updateStatus(mission.id, {
status: 'APPROVED',
review: 'All facings verified, compliant.',
});Mission statuses
| Status | Description |
|---|---|
PLANNED | Mission created, not yet started |
IN_PROGRESS | Rep has started the store visit |
SUBMITTED | Rep has submitted observations for review |
APPROVED | Supervisor accepted the submission |
REJECTED | Supervisor rejected the submission |
Creating a route
A Route can be created with its stops in one call. Each stop becomes a Mission at the given locationId.
const route = await tenant.routes.create({
source: 'platform',
name: 'Brussels North — Week 30',
assignedUserId: 'usr_rep01',
stops: [
{ locationId: 'loc_abc123', sequence: 1, scopeIds: ['sku_beer_001'] },
{ locationId: 'loc_def456', sequence: 2, scopeIds: ['sku_beer_001', 'sku_beer_002'] },
{ locationId: 'loc_ghi789', sequence: 3 },
],
});
console.log(route.id); // "rte_xyz123"
console.log(route.status); // "pending"
console.log(route.missions); // Mission[] — one per stopSalesforce-pulled routes
When source is 'salesforce', the route was created automatically by the SF integration and its externalRef holds the Salesforce visit ID. You can still update the assignee and status via the SDK.
Listing and filtering routes
// All routes assigned to me
const myRoutes = await tenant.routes.list({ mine: true });
// All in-progress routes for a rep
const activeRoutes = await tenant.routes.list({
assignedUserId: 'usr_rep01',
status: 'in_progress',
});
// Only Salesforce-originated routes
const sfRoutes = await tenant.routes.list({ source: 'salesforce' });Updating a route
// Reassign to another rep
await tenant.routes.update(route.id, { assignedUserId: 'usr_rep02' });
// Mark the route completed
await tenant.routes.update(route.id, { status: 'completed' });
// Rename
await tenant.routes.update(route.id, { name: 'Brussels North — Week 30 (revised)' });Route statuses
| Status | Description |
|---|---|
pending | Route created, rep has not started |
in_progress | At least one mission is in progress |
completed | All missions completed |
cancelled | Route was cancelled before completion |
End-to-end example
Create a route from a Salesforce visit, then walk the rep through each stop:
// 1. Create the route (SF integration typically does this automatically)
const route = await tenant.routes.create({
source: 'salesforce',
externalRef: 'SF_VISIT_00ABC',
assignedUserId: 'usr_rep01',
name: 'Duvel Week 30 run',
stops: [
{ locationId: 'loc_store_001', sequence: 1, scopeIds: ['sku_duvel_330'] },
{ locationId: 'loc_store_002', sequence: 2, scopeIds: ['sku_duvel_330'] },
],
});
// 2. Fetch the route with its missions
const loaded = await tenant.routes.get(route.id);
const [first, second] = loaded.missions ?? [];
// 3. Rep works through stop 1
await tenant.missions.updateStatus(first.id, { status: 'IN_PROGRESS' });
// ... rep captures observations at loc_store_001 ...
await tenant.missions.updateStatus(first.id, { status: 'SUBMITTED' });
// 4. Rep works through stop 2
await tenant.missions.updateStatus(second.id, { status: 'IN_PROGRESS' });
// ... rep captures observations at loc_store_002 ...
await tenant.missions.updateStatus(second.id, { status: 'SUBMITTED' });
// 5. Mark route done
await tenant.routes.update(route.id, { status: 'completed' });Next steps
- Observations — Capture photo data within a mission visit
- CV Jobs — Run computer vision on captured observations
- Webhooks — React to mission status changes in real time