KLIQ|Developers
Field Operations

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

POST/v1/tenants/{tenantId}/missionsCreate a mission for a location
GET/v1/tenants/{tenantId}/missionsList missions with optional filters
GET/v1/tenants/{tenantId}/missions/{id}Get a single mission
PATCH/v1/tenants/{tenantId}/missions/{id}Advance mission status or reassign
POST/v1/tenants/{tenantId}/routesCreate a route (with optional stops)
GET/v1/tenants/{tenantId}/routesList routes with optional filters
GET/v1/tenants/{tenantId}/routes/{id}Get a single route (includes missions)
PATCH/v1/tenants/{tenantId}/routes/{id}Update route status, assignee, or name

Creating 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

StatusDescription
PLANNEDMission created, not yet started
IN_PROGRESSRep has started the store visit
SUBMITTEDRep has submitted observations for review
APPROVEDSupervisor accepted the submission
REJECTEDSupervisor 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 stop

Salesforce-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

StatusDescription
pendingRoute created, rep has not started
in_progressAt least one mission is in progress
completedAll missions completed
cancelledRoute 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