{"generatedAt":"2026-10-03T18:50:32.982Z","product":{"slug":"routes-navigation","name":"Routes & Navigation","summary":"Routes, matrices, optimization, map matching, predictive ETAs, and turn-by-turn navigation.","stateModel":"hybrid","platforms":["REST","Android","iOS","Automotive","Linux","React Native"],"auth":{"type":"Restricted static key (current) or legacy OAuth, plus SDK entitlement","guidance":"Current core REST routing uses the restricted static-key query contract; legacy OAuth requires its issued host/path generation. Route calls are stateless, while navigation requires an entitled, lifecycle-aware SDK session."}},"ownership":{"classification":"hybrid-provider-application","boundary":"Routes & Navigation combines request/response capabilities with durable sessions, workspaces, releases, reviews, or agent runs. Persist the business journey independently from any one provider response.","applicationRule":"The application owns business identity, expected version, command idempotency, evidence receipts, audit, reconciliation, and downstream side effects even when Mappls owns provider resource state."},"coverage":{"slug":"routes-navigation","name":"Routes & Navigation","stateModel":"hybrid","ownership":"hybrid-provider-application","accent":"#ff7a45","journeyCount":4,"boundary":"Routes & Navigation combines request/response capabilities with durable sessions, workspaces, releases, reviews, or agent runs. Persist the business journey independently from any one provider response.","aggregates":["incident","navigation session","trip itinerary","route planning session"],"journeySlugs":["emergency-incident-response","navigation-session","durable-weekend-itinerary","ios-direction-planning-handoff"],"sampleSlugs":["incident-dispatch","trip-planner","deep-link-journey-host"],"tutorialSlugs":["route-preview","delivery-eta","mappls-mcp-agent","a2a-solution-coordination","oauth-server-integration","navigation-deep-link","distance-matrix-dispatch","traffic-aware-commute","intouch-trip-lifecycle","cordova-release-hardening","deep-link-attribution-resilience","flutter-production-lifecycle","ios-sdk-production-readiness","ios-direction-geofence-handoffs","react-native-native-parity","widget-host-production","xamarin-maintenance-migration"],"useCaseSlugs":["last-mile-delivery","ride-hailing","field-service","energy-grid-resilience","insurance-claims","hospital-care-logistics","emergency-response","connected-vehicle","travel-discovery","telecom-network-care"],"contractSlugs":["core-location-get-api-places-search-json-autosuggest-api","core-location-get-rest-key-rev-geocode-reverse-geocode-api","core-location-get-rest-key-resources-profile-geopositions-distance-matrix-api","core-location-get-rest-key-resources-profile-geopositions-routing-api","intouch-get-devices-gets-the-live-data-of-devices","intouch-get-devices-deviceid-events-gets-the-historical-location-events-of-a-device"],"sourceGuideSlugs":["mappls-rest-apis","mappls-intouch-rest-apis","mapmyindia-intouch-rest-apis","mappls-android-sdk","mappls-ios-sdk","mappls-react-native-sdk","mapmyindia-maps-vectorsdk-android","mapmyindia-maps-vectorsdk-ios","mappls-direction-ui-ios-distribution","mappls-direction-ui-ios-distribution-base"],"totals":{"states":27,"transitions":31,"failurePlans":17,"durableRecords":16,"operationalSignals":28}},"controlLayers":[{"id":"identity","title":"Identity and aggregate boundary","question":"What durable thing is being operated?","implementation":"Use stable business and provider identifiers for incident, navigation session, trip itinerary, route planning session; never infer identity from display text or the latest coordinates.","proof":"Duplicate creation, resource rebinding, tenant isolation, and retirement tests."},{"id":"authority","title":"Actor authority","question":"Who may advance each transition?","implementation":"Authorize every command against the named journey actors: Call taker, Dispatcher, Responder, Incident commander, Telematics service, Driver, Navigation application, Mappls navigation SDK, Operations backend, Traveller, Collaborator, Mappls discovery service, Mappls routing service, Traveler, Host application, MapplsDirectionUI, Navigation adapter. Persist the attributable actor, tenant, purpose, and policy decision.","proof":"Role, resource, tenant, purpose, and human-approval denial tests."},{"id":"commands","title":"Commands and concurrency","question":"How are retries and races made safe?","implementation":"Require a command idempotency key and expected aggregate version. Cache the canonical result, reject key reuse with different intent, and reconcile ambiguous timeouts before retry.","proof":"Exact replay, stale-version rejection, concurrent-writer, timeout, and restart tests."},{"id":"evidence","title":"Evidence and durable records","question":"What proves each state?","implementation":"Persist immutable receipts and revisions around these catalog records: Incident aggregate, Location decision, Assignment decision, Telemetry envelope, Review record, Route intent, Session checkpoint, Navigation trace, Trip aggregate, Itinerary stop, Route revision, Audit and outbox, Route plan, Route handoff candidate, Handoff attempt. Keep event time, receipt time, source identity, hashes, and retention policy separate.","proof":"Missing, malformed, late, duplicate, conflicting, and redacted-evidence tests."},{"id":"events","title":"Events and side effects","question":"How do downstream systems learn what committed?","implementation":"Commit aggregate state, audit, and a transactional outbox together. Sign deliveries, bound retries, dead-letter exhaustions, and preserve delivery attempts without changing business history.","proof":"Atomic commit, signature, retry, lease fencing, dead-letter, replay, and ordering tests."},{"id":"recovery","title":"Recovery and reconciliation","question":"What happens when systems disagree?","implementation":"Treat timeouts as unknown outcomes, poll or consume authoritative evidence, compare versions, append a reconciliation decision, and use compensation instead of destructive history edits.","proof":"Provider timeout, callback-before-response, delayed event, outage, restart, and manual-recovery drills."},{"id":"privacy","title":"Privacy and human control","question":"Which data and decisions are sensitive?","implementation":"Minimize precise location and media, scope retention, redact derived data deliberately, and require attributable approval for dispatch, publication, access, closure, and destructive change where consequential.","proof":"Least-privilege, consent expiry, separation-of-duties, retention, export, revocation, and redaction tests."},{"id":"operations","title":"Operations and release","question":"Can operators see and recover the journey?","implementation":"Expose state age, source freshness, stuck commands, retries, reconciliation lag, outbox depth, terminal outcomes, and per-aggregate audit. Roll out behind explicit acceptance gates.","proof":"SLO alerts, support lookup, bulk reconciliation, rollback, backup restore, regional failover, and incident drills."}],"journeys":[{"slug":"emergency-incident-response","title":"Coordinated incident response","eyebrow":"Search + Routes + InTouch · command and evidence lifecycle","productSlug":"routes-navigation","stateModel":"stateful","summary":"Resolve an incident location, select a capable available responder, route and observe the unit, adapt to hazards, establish arrival, resolve with evidence, and review every decision.","aggregate":"incident","actors":["Call taker","Dispatcher","Responder","Incident commander","Telematics service"],"sourceGuideSlugs":["mappls-rest-apis","mappls-intouch-rest-apis","mapmyindia-intouch-rest-apis"],"contractSlugs":["core-location-get-api-places-search-json-autosuggest-api","core-location-get-rest-key-rev-geocode-reverse-geocode-api","core-location-get-rest-key-resources-profile-geopositions-distance-matrix-api","core-location-get-rest-key-resources-profile-geopositions-routing-api","intouch-get-devices-gets-the-live-data-of-devices","intouch-get-devices-deviceid-events-gets-the-historical-location-events-of-a-device"],"sampleSlug":"incident-dispatch","states":[{"id":"reported","label":"Reported","meaning":"A stable CAD or operations identifier, incident type, severity, caller reference, required capability, and location intent are recorded.","recovery":"Reconcile creation by external incident ID; never mint a second incident because a response timed out."},{"id":"located","label":"Located","meaning":"A provider-backed Mappls identity, coordinate, formatted address, confidence, and resolution method are committed.","recovery":"Require operator confirmation for weak or ambiguous candidates while retaining the original report."},{"id":"dispatched","label":"Dispatched","meaning":"A capable available unit is selected with matrix ETA, route identity, constraints, and attributable rationale.","recovery":"Reconcile unit availability and the incident version before any reassignment."},{"id":"en_route","label":"En route","meaning":"The assigned unit accepted and current event-time telemetry drives route progress and ETA.","recovery":"Retain late observations as evidence without allowing them to replace current progress."},{"id":"on_scene","label":"On scene","meaning":"Distance, speed, and dwell policy establish arrival; scene hazards and coordination remain active.","recovery":"If evidence is weak, keep the unit en route and request a deliberate operator override rather than inferring arrival."},{"id":"resolved","label":"Resolved","meaning":"Outcome, responsible responder, and external evidence references are committed.","recovery":"Corrections append evidence or create a linked follow-up incident; they do not erase the resolution event."},{"id":"reviewed","label":"Reviewed","meaning":"A commander signs off the replay, disposition, response timings, telemetry count, hazards, and evidence completeness.","recovery":"Keep review immutable and issue a supplemental review when later evidence changes conclusions.","terminal":true}],"transitions":[{"command":"report_incident","actor":"Call taker","from":[],"to":"reported","event":"incident.reported","idempotency":"Use the external CAD or operations identity across retries."},{"command":"resolve_location","actor":"Dispatcher","from":["reported"],"to":"located","event":"incident.located","idempotency":"Bind the accepted candidate, method, confidence, and operator decision to one command."},{"command":"dispatch","actor":"Dispatcher","from":["located"],"to":"dispatched","event":"incident.dispatched","idempotency":"Compare incident version and reserve the selected unit under the same command identity."},{"command":"accept_dispatch","actor":"Responder","from":["dispatched"],"to":"en_route","event":"dispatch.accepted","idempotency":"The assigned unit generates and persists a command ID before transmission."},{"command":"record_position","actor":"Telematics service","from":["en_route"],"to":"en_route","event":"unit.position_recorded","idempotency":"Use provider event identity and preserve event and receipt time."},{"command":"confirm_arrival","actor":"Responder","from":["en_route"],"to":"on_scene","event":"incident.arrived","idempotency":"Bind distance, speed, dwell, policy version, and incident version."},{"command":"resolve","actor":"Responder","from":["on_scene"],"to":"resolved","event":"incident.resolved","idempotency":"Commit outcome, responder, evidence manifest, and outbox atomically."},{"command":"review","actor":"Incident commander","from":["resolved"],"to":"reviewed","event":"incident.reviewed","idempotency":"Review identity and incident terminal version form the stable key."}],"invariants":["One external report maps to one incident aggregate.","Only available units with the required capability are eligible for ranking.","A unit is assigned to at most one active incident in the same operational context.","Only the assigned unit can accept dispatch and publish operational telemetry.","Raw telemetry preserves event and receipt time; late evidence never regresses latest state.","Arrival requires explicit distance, speed, and dwell evidence.","Resolution cannot occur without external evidence references."],"records":[{"name":"Incident aggregate","purpose":"Business identity, lifecycle, location, assignment, hazards, outcome, and review.","keyFields":["incidentId","externalIncidentId","state","version","severity","requiredCapability"]},{"name":"Location decision","purpose":"Provider-backed location and human confirmation evidence.","keyFields":["mapplsPin","coordinate","formattedAddress","method","confidence"]},{"name":"Assignment decision","purpose":"Capability, availability, matrix, route, constraints, and selection rationale.","keyFields":["unitId","routeId","capabilities","eta","selectedBy","reason"]},{"name":"Telemetry envelope","purpose":"Immutable responder position and vehicle evidence.","keyFields":["providerEventId","unitId","eventTime","receivedTime","position","quality"]},{"name":"Review record","purpose":"Attributable disposition and metrics derived from committed events.","keyFields":["reviewer","disposition","timings","positionCount","hazardCount"]}],"failures":[{"trigger":"Caller location is ambiguous","detection":"Search candidates are low-confidence, far apart, or conflict with caller/device context.","recovery":"Keep the report unresolved, ask a targeted confirmation question, and record the chosen candidate and reason."},{"trigger":"Two dispatchers select the same unit","detection":"Unit reservation or incident expected version conflicts.","recovery":"Return the current assignments and require an intentional new selection from refreshed availability."},{"trigger":"Telemetry is late or out of order","detection":"Event time is behind the incident position watermark.","recovery":"Store it, emit a late-evidence event, and do not replace latest route progress."},{"trigger":"Route becomes unsafe after dispatch","detection":"A new hazard, closure, or restriction intersects the current route or approach policy.","recovery":"Record the hazard, calculate a versioned replacement route, and keep the last safe guidance until accepted."},{"trigger":"Resolution side effects fail","detection":"Incident is resolved while notification or downstream outbox entries remain pending.","recovery":"Retry the outbox independently; never re-resolve the incident to trigger delivery."}],"observability":["Report-to-location and call-to-dispatch time","Eligible responder count and rejected capability reasons","Matrix ranking, selected unit, override, and route latency","Telemetry freshness, ordering lag, and route revision","Hazard age and approach-policy changes","Arrival evidence pass/fail and override rate","Scene-to-resolution time and evidence completeness","Outbox backlog and review completion"],"website":"/journeys/emergency-incident-response"},{"slug":"navigation-session","title":"Recoverable navigation session","eyebrow":"Navigation · device session lifecycle","productSlug":"routes-navigation","stateModel":"hybrid","summary":"Move from route intent through preview, guidance, reroute, arrival, and cleanup while surviving process, sensor, and network interruption.","aggregate":"navigation session","actors":["Driver","Navigation application","Mappls navigation SDK","Operations backend"],"sourceGuideSlugs":["mappls-android-sdk","mappls-ios-sdk","mappls-react-native-sdk","mapmyindia-maps-vectorsdk-android","mapmyindia-maps-vectorsdk-ios"],"contractSlugs":[],"sampleSlug":"trip-planner","states":[{"id":"draft","label":"Draft","meaning":"Origin, destination, stops, vehicle profile, and constraints are incomplete or editable.","recovery":"Persist intent separately from SDK runtime state."},{"id":"preview","label":"Preview","meaning":"Alternatives and trade-offs are visible but guidance and sensor use have not started.","recovery":"Refresh stale route and traffic inputs before starting."},{"id":"navigating","label":"Navigating","meaning":"Guidance owns an active route and consumes position, progress, traffic, and user commands.","recovery":"Checkpoint minimal resumable intent and progress; reinitialize SDK resources after process death."},{"id":"rerouting","label":"Rerouting","meaning":"The active route is temporarily superseded by a recalculation caused by deviation, traffic, or destination change.","recovery":"Continue safe guidance on the last valid route until the replacement is accepted."},{"id":"arrived","label":"Arrived","meaning":"Arrival policy passed and the application is waiting for confirmation or final trip actions.","recovery":"Require an explicit end or continue decision when multiple stops remain."},{"id":"ended","label":"Ended","meaning":"Sensors, audio, observers, foreground services, and SDK session resources are released.","recovery":"Cleanup is idempotent and safe after partial initialization.","terminal":true}],"transitions":[{"command":"calculate_route","actor":"Navigation application","from":["draft","preview"],"to":"preview","event":"route.calculated","idempotency":"Hash normalized intent and constraints for request deduplication and caching."},{"command":"start_guidance","actor":"Driver","from":["preview"],"to":"navigating","event":"navigation.started","idempotency":"Persist a session command ID before starting foreground resources."},{"command":"request_reroute","actor":"Navigation application","from":["navigating","rerouting"],"to":"rerouting","event":"reroute.requested","idempotency":"Coalesce equivalent deviations while one calculation is outstanding."},{"command":"accept_reroute","actor":"Mappls navigation SDK","from":["rerouting"],"to":"navigating","event":"route.updated","idempotency":"Apply only a response matching the latest route-intent version."},{"command":"confirm_arrival","actor":"Navigation application","from":["navigating"],"to":"arrived","event":"navigation.arrived","idempotency":"Arrival policy version and stop ID form the stable key."},{"command":"end_session","actor":"Driver","from":["preview","navigating","rerouting","arrived"],"to":"ended","event":"navigation.ended","idempotency":"Cleanup must tolerate repeated calls and partial startup."}],"invariants":["Only one guidance session owns foreground navigation resources at a time.","Every route result is applied only to the intent version that requested it.","The last valid route remains available while a reroute is pending.","Arrival requires an explicit distance, speed, dwell, and stop policy.","End releases every observer, sensor, audio, and service resource exactly once in effect."],"records":[{"name":"Route intent","purpose":"Portable origin, stops, profile, constraints, and version.","keyFields":["intentId","version","waypoints","profile","constraints"]},{"name":"Session checkpoint","purpose":"Minimal recoverable progress without persisting unsafe SDK internals.","keyFields":["sessionId","intentVersion","routeId","legIndex","lastPositionTime"]},{"name":"Navigation trace","purpose":"Privacy-bounded operational and quality evidence.","keyFields":["sessionId","eventType","occurredAt","routeVersion","quality"]}],"failures":[{"trigger":"Application process is killed","detection":"A persisted active checkpoint exists without a live runtime owner.","recovery":"Recreate resources, validate destination intent, recalculate if stale, and ask before resuming guidance."},{"trigger":"GNSS quality degrades","detection":"Accuracy, age, speed consistency, or map-matching confidence crosses policy.","recovery":"Surface degraded positioning, use supported dead-reckoning inputs, and avoid false reroutes."},{"trigger":"Reroute response arrives after destination changed","detection":"Response intent version is older than the active intent.","recovery":"Discard it and keep the latest calculation; never apply by arrival order alone."},{"trigger":"Network disappears","detection":"Online route, traffic, or search dependency fails while local guidance remains active.","recovery":"Keep last valid guidance, expose freshness, and use entitled offline capability when available."}],"observability":["Route calculation latency and alternative selection","Position age, accuracy, and map-matching confidence","Reroute cause, time, cancellation, and supersession","Guidance session starts without matching cleanup","Arrival false-positive and manual-override rate","Crash/restart recovery outcome"],"website":"/journeys/navigation-session"},{"slug":"durable-weekend-itinerary","title":"Durable multi-stop itinerary","eyebrow":"Search + Routes · intent and route revisions","productSlug":"routes-navigation","stateModel":"hybrid","summary":"Discover provider-backed places, preserve their Mappls Pins in a versioned itinerary, preview the exact ordered route, invalidate stale plans on edits, and retain visit or skip progress through completion.","aggregate":"trip itinerary","actors":["Traveller","Collaborator","Mappls discovery service","Mappls routing service"],"sourceGuideSlugs":["mappls-rest-apis"],"contractSlugs":["core-location-get-api-places-search-json-autosuggest-api","core-location-get-rest-key-resources-profile-geopositions-routing-api"],"sampleSlug":"trip-planner","states":[{"id":"draft","label":"Draft","meaning":"An ordered, bounded set of provider-backed places represents current trip intent without claiming a valid route.","recovery":"Resolve edits by aggregate version and retain stable Mappls Pins; never merge by display label."},{"id":"planned","label":"Planned","meaning":"A route revision is bound to the exact ordered stop identities, travel profile, provider response, and planning time.","recovery":"Any stop, order, profile, or constraint change invalidates the revision and returns the itinerary to draft."},{"id":"active","label":"Active","meaning":"The traveller started the current route revision and each next stop receives an explicit visited or skipped outcome.","recovery":"Resume from durable progress; recalculate from current trusted context instead of replaying stale guidance."},{"id":"paused","label":"Paused","meaning":"An attributable interruption stops progress without discarding saved stops, outcomes, or route identity.","recovery":"Refresh time-sensitive context and require deliberate resume or cancellation."},{"id":"completed","label":"Completed","meaning":"Every stop is visited or explicitly skipped and the terminal itinerary, route revision, outcomes, and event history are retained.","recovery":"Later edits create a new trip or linked revision rather than rewriting completed history.","terminal":true},{"id":"cancelled","label":"Cancelled","meaning":"A named actor ended the itinerary with a reason while retaining all committed place, route, and progress evidence.","recovery":"Create a linked replacement trip when intent returns rather than reactivating terminal history.","terminal":true}],"transitions":[{"command":"create_trip","actor":"Traveller","from":[],"to":"draft","event":"trip.created","idempotency":"Use a client trip command ID before the first network attempt."},{"command":"add_or_reorder_stop","actor":"Traveller","from":["draft","planned"],"to":"draft","event":"trip.sequence_changed","idempotency":"Compare trip version and bind every saved item to a unique Mappls Pin."},{"command":"preview_route","actor":"Mappls routing service","from":["draft"],"to":"planned","event":"trip.route_previewed","idempotency":"Hash ordered pins, profile, constraints, departure intent, and aggregate version."},{"command":"start_trip","actor":"Traveller","from":["planned"],"to":"active","event":"trip.started","idempotency":"Bind start to the current trip and route revision."},{"command":"pause_trip","actor":"Traveller","from":["active"],"to":"paused","event":"trip.paused","idempotency":"Record the interruption reason once under a stable client command identity."},{"command":"resume_trip","actor":"Traveller","from":["paused"],"to":"active","event":"trip.resumed","idempotency":"Bind resume to the paused aggregate and current route revision."},{"command":"visit_or_skip_next","actor":"Traveller","from":["active"],"to":"active","event":"trip.stop_completed","idempotency":"Generate one command identity per stop outcome; require a reason for skip."},{"command":"complete_trip","actor":"Traveller","from":["active"],"to":"completed","event":"trip.completed","idempotency":"Terminal version and command ID identify one completion."},{"command":"cancel_trip","actor":"Traveller","from":["draft","planned","active","paused"],"to":"cancelled","event":"trip.cancelled","idempotency":"One command records actor, reason, previous state, and terminal version."}],"invariants":["Every saved stop originated from provider-backed discovery and retains its Mappls Pin and provenance.","A Mappls Pin occurs at most once in an itinerary.","A route revision is valid only for the exact ordered stop list and constraints that produced it.","Only the next pending stop may receive a visit or skip outcome.","Completion is impossible while any stop remains pending.","Commands are idempotent and compare the expected trip version."],"records":[{"name":"Trip aggregate","purpose":"Business identity, date, party, lifecycle, current route revision, and optimistic version.","keyFields":["tripId","state","version","date","partySize","routeRevision"]},{"name":"Itinerary stop","purpose":"Ordered provider-backed place and progress outcome.","keyFields":["mapplsPin","position","providerProvenance","status","completedAt","skipReason"]},{"name":"Route revision","purpose":"Immutable preview for one exact intent version.","keyFields":["routeId","revision","orderedPins","profile","legs","distance","duration","plannedAt"]},{"name":"Audit and outbox","purpose":"Attributable changes and reliable downstream collaboration or notification.","keyFields":["eventId","aggregateVersion","actor","commandId","outboxStatus"]}],"failures":[{"trigger":"A collaborator edits after route preview","detection":"Current stop identities or aggregate version differ from the route's intent version.","recovery":"Invalidate the route, show the edit, and require a new preview before start."},{"trigger":"Routing succeeds but response is lost","detection":"The same ordered intent and request identity has no committed route revision.","recovery":"Reconcile or repeat the same idempotent request; never attach a response to newer intent."},{"trigger":"A venue becomes unavailable during the trip","detection":"Traveller or fresh provider/business data marks the next stop unavailable.","recovery":"Record an explicit skip with reason, then offer a newly versioned replan from current context."},{"trigger":"Application restarts mid-trip","detection":"A durable active aggregate exists without current client state.","recovery":"Restore visit/skip progress and current revision, refresh stale operational data, and ask before resuming guidance."}],"observability":["Discovery-to-save rate and Mappls Pin continuity","Stop edits, duplicates, limits, and version conflicts","Route preview latency, failures, profiles, and revisions","Time from preview to start and stale-preview invalidation","Visited and skipped stops with reason","Active trips without recent progress","Idempotent replay, outbox backlog, and restart recovery"],"website":"/journeys/durable-weekend-itinerary"},{"slug":"ios-direction-planning-handoff","title":"iOS direction planning and navigation handoff","eyebrow":"MapplsDirectionUI · route candidate lifecycle","productSlug":"routes-navigation","stateModel":"hybrid","summary":"Own route intent and revisions in the host app, present MapplsDirectionUI for editing and calculation, validate the selected route callback, and hand off to navigation without confusing a UI request with a started or completed trip.","aggregate":"route planning session","actors":["Traveler","Host application","MapplsDirectionUI","Navigation adapter"],"sourceGuideSlugs":["mappls-direction-ui-ios-distribution","mappls-direction-ui-ios-distribution-base"],"contractSlugs":[],"sampleSlug":"deep-link-journey-host","tutorialSlugs":["ios-direction-geofence-handoffs"],"states":[{"id":"draft","label":"Draft","meaning":"The host owns one route intent, traveler context, and revision before presenting provider UI.","recovery":"Restore only normalized locations and host preferences; never serialize a view controller, delegate, or provider route object."},{"id":"editing","label":"Editing","meaning":"One presented controller generation owns source, destination, via points, options, delegates, dismissal, and accessibility focus.","recovery":"Dismiss and dispose the active generation once; a new presentation receives a new generation and route revision."},{"id":"calculating","label":"Calculating","meaning":"The provider surface is resolving route alternatives for the current immutable location and option revision.","recovery":"Retain the host draft and expose retry or edit; never reuse candidates calculated for an older revision."},{"id":"candidates_ready","label":"Candidates ready","meaning":"One or more provider route objects are visible for comparison but remain controller-scoped candidates.","recovery":"If stops or route options change, invalidate the full candidate set and calculate again."},{"id":"selected","label":"Selected","meaning":"The traveler selected an in-range route index and the adapter copied a bounded route handoff value plus the exact location revision.","recovery":"A subsequent edit invalidates selection; do not persist the opaque Route instance as application state."},{"id":"handoff_pending","label":"Handoff pending","meaning":"The documented start-navigation callback requested a host-owned navigation action, but no target navigator acknowledgement exists yet.","recovery":"Retry with the same handoff identity or return visibly to selection; never report navigation as active from the button callback alone."},{"id":"handed_off","label":"Handed off","meaning":"The configured navigation adapter accepted the normalized route request and returned its own attributable session identity or acknowledgement.","recovery":"Navigation progress and completion belong to the selected navigation product's separate lifecycle.","terminal":true},{"id":"cancelled","label":"Cancelled","meaning":"The traveler dismissed or backed out and the host recorded one terminal cancellation without a route handoff.","recovery":"Renewed intent creates a new planning session rather than resurrecting the disposed controller.","terminal":true}],"transitions":[{"command":"create_plan","actor":"Host application","from":[],"to":"draft","event":"route_plan.created","idempotency":"One external journey intent maps to one route-planning aggregate across retries."},{"command":"open_direction_ui","actor":"Traveler","from":["draft","selected"],"to":"editing","event":"route_plan.editor_opened","idempotency":"One command creates one presentation generation and one delegate ownership record."},{"command":"request_routes","actor":"Traveler","from":["editing"],"to":"calculating","event":"route_plan.calculation_requested","idempotency":"Hash normalized locations, options, and revision so duplicate requests share one logical calculation."},{"command":"receive_routes","actor":"MapplsDirectionUI","from":["calculating"],"to":"candidates_ready","event":"route_plan.candidates_received","idempotency":"Accept only the active generation and revision; repeated callbacks replace no committed state."},{"command":"select_route","actor":"Traveler","from":["candidates_ready"],"to":"selected","event":"route_plan.route_selected","idempotency":"Validate selectedRouteIndex against the returned collection and commit one normalized handoff value for the route revision."},{"command":"request_navigation","actor":"Traveler","from":["selected","candidates_ready"],"to":"handoff_pending","event":"route_plan.navigation_requested","idempotency":"Bind callback generation, route revision, selected index, and host command key to one handoff attempt."},{"command":"confirm_handoff","actor":"Navigation adapter","from":["handoff_pending"],"to":"handed_off","event":"route_plan.navigation_handed_off","idempotency":"Persist the target acknowledgement once and let its separate lifecycle own later progress."},{"command":"cancel_plan","actor":"Traveler","from":["draft","editing","calculating","candidates_ready","selected","handoff_pending"],"to":"cancelled","event":"route_plan.cancelled","idempotency":"Repeated back, dismissal, or cancel signals dispose once and return the same terminal outcome."}],"invariants":["Stops, options, route candidates, and selection share one explicit revision.","A selected index is validated before dereferencing its Route candidate.","The provider controller and opaque Route objects never become durable application records.","The start-navigation callback expresses intent, not proof that navigation started or completed.","One presentation generation produces at most one terminal handoff or cancellation.","Credentials and unrestricted location histories never enter route-planning audit events."],"records":[{"name":"Route plan","purpose":"Host-owned normalized stops, options, revision, lifecycle state, and optimistic version.","keyFields":["planId","externalId","state","routeRevision","version","owner"]},{"name":"Route handoff candidate","purpose":"Bounded portable value copied from the active route selection without retaining provider UI objects.","keyFields":["candidateId","routeRevision","selectedIndex","locationDigest","optionDigest","createdAt"]},{"name":"Handoff attempt","purpose":"Immutable request and target acknowledgement separating planning from navigation runtime.","keyFields":["attemptId","candidateId","target","status","targetSessionRef","requestedAt"]},{"name":"Audit and outbox","purpose":"Attributable transitions and exactly-once-in-effect downstream notification.","keyFields":["eventId","aggregateVersion","actor","idempotencyKey","outboxStatus"]}],"failures":[{"trigger":"Route calculation fails or returns no alternatives","detection":"The active controller reports an error or has no valid selected route for the current revision.","recovery":"Keep the editable draft, show a safe error, and allow option or stop revision before retry."},{"trigger":"A delegate callback arrives from an old controller","detection":"The callback presentation generation differs from the aggregate's active generation.","recovery":"Ignore it, dispose its resources, and leave the current route revision unchanged."},{"trigger":"Selected route index is stale or invalid","detection":"The index is outside the current route collection or belongs to a superseded calculation revision.","recovery":"Reject the handoff and require visible reselection from current candidates."},{"trigger":"Navigation target rejects or times out","detection":"No target acknowledgement exists for the handoff identity inside the bounded deadline.","recovery":"Remain handoff pending, expose retry or return-to-selection, and do not claim an active navigation session."}],"observability":["Editor presentation, dismissal, and terminal result by released component version","Calculation latency, failure, and zero-alternative rate","Stop and option revision count before selection","Candidate-to-selection and selection-to-handoff conversion","Invalid index, stale generation, duplicate callback, and late callback rejection","Handoff acknowledgement latency and target rejection rate","Idempotency replay and optimistic version conflict rate"],"website":"/journeys/ios-direction-planning-handoff"}],"evidence":{"contracts":[{"slug":"core-location-get-api-places-search-json-autosuggest-api","method":"GET","path":"/api/places/search/json","summary":"AutoSuggest API","contractStatus":"legacy-source","stateModel":"stateless","journeyRole":"request-response","website":"/api-reference/core-location-get-api-places-search-json-autosuggest-api"},{"slug":"core-location-get-rest-key-rev-geocode-reverse-geocode-api","method":"GET","path":"/{REST_KEY}/rev_geocode","summary":"Reverse Geocode API","contractStatus":"legacy-source","stateModel":"stateless","journeyRole":"request-response","website":"/api-reference/core-location-get-rest-key-rev-geocode-reverse-geocode-api"},{"slug":"core-location-get-rest-key-resources-profile-geopositions-distance-matrix-api","method":"GET","path":"/{rest-key}/{resources}/{profile}/{geopositions}","summary":"Distance Matrix API","contractStatus":"legacy-source","stateModel":"stateless","journeyRole":"request-response","website":"/api-reference/core-location-get-rest-key-resources-profile-geopositions-distance-matrix-api"},{"slug":"core-location-get-rest-key-resources-profile-geopositions-routing-api","method":"GET","path":"/{REST_KEY}/{resources}/{profile}/{geopositions}","summary":"Routing API","contractStatus":"legacy-source","stateModel":"stateless","journeyRole":"request-response","website":"/api-reference/core-location-get-rest-key-resources-profile-geopositions-routing-api"},{"slug":"intouch-get-devices-gets-the-live-data-of-devices","method":"GET","path":"/devices","summary":"Gets the live data of devices.","contractStatus":"legacy-source","stateModel":"stateful","journeyRole":"observe","website":"/api-reference/intouch-get-devices-gets-the-live-data-of-devices"},{"slug":"intouch-get-devices-deviceid-events-gets-the-historical-location-events-of-a-device","method":"GET","path":"/devices/{deviceId}/events","summary":"Gets the historical location events of a device.","contractStatus":"legacy-source","stateModel":"stateful","journeyRole":"observe","website":"/api-reference/intouch-get-devices-deviceid-events-gets-the-historical-location-events-of-a-device"}],"guides":[{"slug":"mappls-rest-apis","title":"Mappls Map APIs (REST) !","summary":"Building Blocks to Add Powerful Location Intelligence & Mapping Functionality to your Apps","kind":"REST API","maturity":"current","platforms":["REST"],"website":"/reference/mappls-rest-apis"},{"slug":"mappls-intouch-rest-apis","title":"Mappls Intouch REST Apis","summary":"A Mappls rest api for routes navigation, tracking telematics, capture feedback, identity platform across REST.","kind":"REST API","maturity":"current","platforms":["REST"],"website":"/reference/mappls-intouch-rest-apis"},{"slug":"mapmyindia-intouch-rest-apis","title":"Mapmyindia Intouch REST Apis","summary":"A Mappls rest api for tracking telematics across REST.","kind":"REST API","maturity":"deprecated","platforms":["REST"],"website":"/reference/mapmyindia-intouch-rest-apis"},{"slug":"mappls-android-sdk","title":"Mappls Android SDK","summary":"A collection of Mappls's Map and others SDKs for Native android Development.","kind":"SDK","maturity":"current","platforms":["Android"],"website":"/reference/mappls-android-sdk"},{"slug":"mappls-ios-sdk","title":"Mappls iOS SDK","summary":"A collection of Mappls's Map and others SDKs for Native iOS Development.","kind":"SDK","maturity":"current","platforms":["iOS"],"website":"/reference/mappls-ios-sdk"},{"slug":"mappls-react-native-sdk","title":"Mappls React Native SDK","summary":"A Mappls sdk for maps, search places, routes navigation, tracking telematics, gis analytics, widgets deep links, capture feedback, identity platform across React Native.","kind":"SDK","maturity":"current","platforms":["React Native"],"website":"/reference/mappls-react-native-sdk"},{"slug":"mapmyindia-maps-vectorsdk-android","title":"MapmyIndia Vector Map Android SDK","summary":"MapmyIndia Vector Maps SDK for Native Android Development with REST API Kit","kind":"SDK","maturity":"deprecated","platforms":["Android"],"website":"/reference/mapmyindia-maps-vectorsdk-android"},{"slug":"mapmyindia-maps-vectorsdk-ios","title":"Mapmyindia Maps VectorSDK IOS","summary":"MapmyIndia Vector Maps SDK for Native iOS Development with REST API Kit","kind":"SDK","maturity":"deprecated","platforms":["iOS"],"website":"/reference/mapmyindia-maps-vectorsdk-ios"},{"slug":"mappls-direction-ui-ios-distribution","title":"MapplsDirectionUI for iOS","summary":"Mappls Direction UI Native for iOS distributed via the SPM (Swift Package Manager).","kind":"Distribution","maturity":"distribution","platforms":["iOS"],"website":"/reference/mappls-direction-ui-ios-distribution"},{"slug":"mappls-direction-ui-ios-distribution-base","title":"MapplsDirectionUI for iOS","summary":"A versioned iOS distribution package used to integrate maps, search places, routes navigation, tracking telematics, capture feedback, identity platform into an application.","kind":"Distribution","maturity":"distribution","platforms":["iOS"],"website":"/reference/mappls-direction-ui-ios-distribution-base"}],"samples":[{"slug":"incident-dispatch","name":"Incident Dispatch","description":"Resolve an incident, choose a capable available responder, route, track evidence, enforce arrival, and review.","stack":["Node.js","Browser control room","Search adapter","Routes adapter","InTouch adapter"],"implementation":"full-stack-reference","verifiedTestCount":8,"downloadPath":"/downloads/incident-dispatch.zip","website":"/samples/incident-dispatch"},{"slug":"trip-planner","name":"Weekend Trip Planner","description":"Preserve Mappls place identity through a durable ordered itinerary, route revisions, progress, and completion.","stack":["Node.js","Responsive itinerary UI","Search adapter","Routes adapter"],"implementation":"full-stack-reference","verifiedTestCount":8,"downloadPath":"/downloads/trip-planner.zip","website":"/samples/trip-planner"},{"slug":"deep-link-journey-host","name":"Deep-link & Native UI Journey Host","description":"Run complete direction-planning and geofence-draft lifecycles around Mappls iOS UI adapters, with an exact documented navigation-link fallback and no invented callback or provider publication claim.","stack":["Node.js","Responsive two-lane journey UI","iOS native fixture adapters","Durable evidence store"],"implementation":"full-stack-reference","verifiedTestCount":11,"downloadPath":"/downloads/deep-link-journey-host.zip","website":"/samples/deep-link-journey-host"}],"tutorials":[{"slug":"route-preview","title":"Build a route preview with alternatives","outcome":"A production-pattern route comparison view.","level":"Intermediate","duration":"35 min","website":"/tutorials/route-preview"},{"slug":"delivery-eta","title":"Track a delivery with a trustworthy ETA","outcome":"A stateful live-delivery journey with recovery and replay.","level":"Advanced","duration":"90 min","website":"/tutorials/delivery-eta"},{"slug":"mappls-mcp-agent","title":"Give an AI agent grounded Mappls tools","outcome":"An agent that can reason about real places without inventing APIs.","level":"Intermediate","duration":"30 min","website":"/tutorials/mappls-mcp-agent"},{"slug":"a2a-solution-coordination","title":"Coordinate a complete Mappls A2A journey","outcome":"A restart-safe OAuth-capable host that keeps transport identity, provider-read purpose, protocol completion, human acceptance, entitlement, writes, and production approval separate.","level":"Advanced","duration":"90 min","website":"/tutorials/a2a-solution-coordination"},{"slug":"oauth-server-integration","title":"Call Mappls safely from a trusted server","outcome":"A credential-safe live server boundary with typed errors, timeout, retry, and provider provenance.","level":"Intermediate","duration":"35 min","website":"/tutorials/oauth-server-integration"},{"slug":"navigation-deep-link","title":"Hand off to navigation with a resilient deep link","outcome":"A tested app-to-navigation hand-off across installed and uninstalled states.","level":"Beginner","duration":"20 min","website":"/tutorials/navigation-deep-link"},{"slug":"distance-matrix-dispatch","title":"Rank responders with a distance matrix","outcome":"An explainable ETA-based dispatch shortlist rather than a straight-line guess.","level":"Intermediate","duration":"45 min","website":"/tutorials/distance-matrix-dispatch"},{"slug":"traffic-aware-commute","title":"Build a traffic-aware commute assistant","outcome":"A route comparison experience that communicates freshness and uncertainty.","level":"Intermediate","duration":"50 min","website":"/tutorials/traffic-aware-commute"},{"slug":"intouch-trip-lifecycle","title":"Reconcile a complete InTouch trip lifecycle","outcome":"A restart-safe connected trip with replay, late evidence, and closure reconciliation.","level":"Advanced","duration":"2 hr","website":"/tutorials/intouch-trip-lifecycle"},{"slug":"cordova-release-hardening","title":"Qualify a Cordova location release","outcome":"A versioned hybrid release with reproducible native builds, safe teardown, and rollback.","level":"Advanced","duration":"80 min","website":"/tutorials/cordova-release-hardening"},{"slug":"deep-link-attribution-resilience","title":"Operate deep links across every hand-off","outcome":"A measurable zero-SDK journey that never confuses a click with arrival.","level":"Advanced","duration":"70 min","website":"/tutorials/deep-link-attribution-resilience"},{"slug":"flutter-production-lifecycle","title":"Production-harden a Flutter location feature","outcome":"A cross-platform feature with stable identity, bounded bridge traffic, and deterministic disposal.","level":"Advanced","duration":"90 min","website":"/tutorials/flutter-production-lifecycle"},{"slug":"ios-sdk-production-readiness","title":"Qualify an iOS Mappls release","outcome":"A clean-device iOS qualification record spanning SDK, widget, tracking, and distribution boundaries.","level":"Advanced","duration":"2 hr","website":"/tutorials/ios-sdk-production-readiness"},{"slug":"ios-direction-geofence-handoffs","title":"Build restart-safe iOS direction and geofence handoffs","outcome":"Two tested, durable iOS handoff journeys with explicit provider and application evidence boundaries.","level":"Advanced","duration":"95 min","website":"/tutorials/ios-direction-geofence-handoffs"},{"slug":"react-native-native-parity","title":"Qualify React Native native parity","outcome":"One JavaScript contract backed by independently qualified Android and iOS behavior.","level":"Advanced","duration":"100 min","website":"/tutorials/react-native-native-parity"},{"slug":"widget-host-production","title":"Operate widgets as untrusted lifecycle surfaces","outcome":"A restart-safe host journey with exact-origin validation and a complete non-widget fallback.","level":"Advanced","duration":"85 min","website":"/tutorials/widget-host-production"},{"slug":"xamarin-maintenance-migration","title":"Harden and migrate a Xamarin location feature","outcome":"A supportable existing integration with explicit compatibility, teardown, and migration evidence.","level":"Advanced","duration":"2 hr","website":"/tutorials/xamarin-maintenance-migration"}],"useCases":[{"slug":"last-mile-delivery","title":"A delivery promise customers can trust","industry":"Logistics","outcome":"Fewer failed deliveries and a live, explainable ETA from checkout to doorstep.","website":"/use-cases/last-mile-delivery"},{"slug":"ride-hailing","title":"A pickup flow that survives the real world","industry":"Mobility","outcome":"Shorter pickup times with fewer calls, cancellations, and unsafe rendezvous points.","website":"/use-cases/ride-hailing"},{"slug":"field-service","title":"Dispatch the right technician, with the right proof","industry":"Utilities","outcome":"Higher first-time-fix rates and auditable work from dispatch through customer sign-off.","website":"/use-cases/field-service"},{"slug":"energy-grid-resilience","title":"Restore the grid from alarm to verified service","industry":"Energy","outcome":"Faster, safer restoration with an explainable view of affected assets, customers, crews, and residual risk.","website":"/use-cases/energy-grid-resilience"},{"slug":"insurance-claims","title":"Evidence-led claims from incident to settlement","industry":"Insurance","outcome":"Faster, more consistent claims decisions with tamper-aware spatial evidence.","website":"/use-cases/insurance-claims"},{"slug":"hospital-care-logistics","title":"Coordinate time-critical care without losing custody","industry":"Healthcare","outcome":"Shorter transfer and specimen journeys with fewer missed hand-offs and a complete chain of operational custody.","website":"/use-cases/hospital-care-logistics"},{"slug":"emergency-response","title":"Route coordinated response under pressure","industry":"Public safety","outcome":"Reduced time to scene and safer decisions across dispatch, responders, and command.","website":"/use-cases/emergency-response"},{"slug":"connected-vehicle","title":"Navigation built for intermittent connectivity","industry":"Automotive","outcome":"Reliable guidance across coverage gaps without giving up traffic, search freshness, or safety.","website":"/use-cases/connected-vehicle"},{"slug":"travel-discovery","title":"Turn inspiration into an itinerary","industry":"Travel","outcome":"More confident trip planning and higher conversion from discovery to booking.","website":"/use-cases/travel-discovery"},{"slug":"telecom-network-care","title":"Operate the network from tower to doorstep","industry":"Telecommunications","outcome":"Faster restoration with better prioritization and fewer repeat dispatches.","website":"/use-cases/telecom-network-care"}]},"releaseGates":["Every command has tenant, actor, purpose, idempotency, expected-version, and authorization evidence.","Every state transition has an objective evidence rule and an explicit recovery path.","Provider and business identities remain distinct, versioned, and reconcilable.","Timeout, retry, duplicate, late, out-of-order, conflict, restart, and outage paths are tested.","Sensitive location, media, identity, and operational evidence has consent, access, retention, and redaction policy.","Audit and outbox commit atomically; signing, delivery, dead-letter, replay, and lease fencing are verified.","Operators can find one aggregate, explain its state, repair safely, and prove who acted.","Live Mappls entitlement, quota, regional behavior, callbacks, and exact provider contracts are validated before production."],"handoffs":{"website":"https://developer.mappls.com/tools/stateful?product=routes-navigation","api":"https://developer.mappls.com/api/stateful-plan?product=routes-navigation","console":"https://developer.mappls.com/console/apps","resource":"mappls://catalog/stateful","tool":"mappls_plan_stateful_integration"},"credentialRule":"The planner accepts no credential, token, secret, precise location, media, or provider resource identifier."}