PlanSolve is still in pre-alpha – Features may change or break. Feedback welcome!

Field Service Quick Start

Step-by-step REST API integration with PowerShell

Get Started in 7 Steps

Learn how to integrate PlanSolve's field service optimization using the REST API with PowerShell. This practical guide walks you through creating vehicles, visits, and solving optimization problems.

Prerequisites:PowerShell and a PlanSolve account
1

Create Vehicles

Define your technicians with shifts, skills, and starting locations

Code Example

json
{
  "id": "tech1",
  "homeLocation": [40.7128, -74.0060],
  "skills": ["repair", "installation"],
  "shifts": [{
    "id": "morning",
    "minStartTime": "2024-01-15T08:00:00",
    "maxEndTime": "2024-01-15T17:00:00"
  }]
}

Explanation

Each vehicle represents a technician with their capabilities. The homeLocation is where they start and stop their day, skills is a flat list of attributes that will be used to match to visits requiring those skills, and shifts specify when the technician is available for work.

2

Create Visits

Define customer visits with time windows, required skills, and priorities

Code Example

json
{
  "id": "visit1",
  "name": "AC Repair - Downtown Office",
  "location": [40.7589, -73.9851],
  "timeWindows": [{
    "minStartTime": "2024-01-15T09:00:00",
    "maxEndTime": "2024-01-15T17:00:00"
  }],
  "serviceDuration": "PT60M",
  "priority": "HIGH",
  "requiredSkills": ["repair"]
}

Explanation

Visits represent customer appointments. Time windows (optional) show when service can be performed, required skills (optional) ensure the right technician is assigned, and priority (optional) helps with scheduling order.

3

Create Request

Combine vehicles and visits into a complete optimization request

Code Example

json
{
  "solver": "field_service",
  "startDate": "2024-01-15",
  "endDate": "2024-01-15",
  "startDateTime": "2024-01-15T08:00:00",
  "endDateTime": "2024-01-15T18:00:00",
  "southwestCorner": [40.7000, -74.0200],
  "northeastCorner": [40.8000, -73.9700],
  "vehicles": [
    {
      "id": "tech1",
      "homeLocation": [40.7128, -74.0060],
      "skills": ["repair", "installation"],
      "shifts": [{
        "id": "morning",
        "minStartTime": "2024-01-15T08:00:00",
        "maxEndTime": "2024-01-15T17:00:00"
      }]
    }
  ],
  "visits": [
    {
      "id": "visit1",
      "name": "AC Repair - Downtown Office",
      "location": [40.7589, -73.9851],
      "timeWindows": [{
        "minStartTime": "2024-01-15T09:00:00",
        "maxEndTime": "2024-01-15T17:00:00"
      }],
      "serviceDuration": "PT60M",
      "priority": "HIGH",
      "requiredSkills": ["repair"]
    }
  ]
}

Explanation

This is your complete optimization request. The solver will find the best routes for your technicians to visit all customers while respecting constraints like skills matching, time windows, and shift availability. Use startDate/endDate to specify the planning range, and optionally use southwestCorner/northeastCorner to define a geographic bounding box that can help optimize the algorithm performance.

4

Create API Key

Generate an API key from your PlanSolve dashboard

Code Example

powershell
# Go to Settings > API Keys in your dashboard
# Click "Generate New API Key"
# Copy the generated key (e.g., "ps_live_abc123...")
# Store it securely in an environment variable

$env:PLANSOLVE_API_KEY="ps_live_abc123..."

Explanation

API keys authenticate your requests and track usage. Never commit them to version control - use environment variables instead.

5

Prepare POST Request

Set up the PowerShell command with your data and API key

Code Example

powershell
# Save your request data to a file
$requestData = @{
    solver = "field_service"
    startDateTime = "2024-01-15T08:00:00"
    endDateTime = "2024-01-15T18:00:00"
    vehicles = @(...)
    visits = @(...)
} | ConvertTo-Json -Depth 10

# Set up Invoke-RestMethod command
Invoke-RestMethod -Uri "https://plansolve.app/api/solve" \
  -Method POST \
  -Headers @{"Content-Type"="application/json"; "X-API-KEY"=$env:PLANSOLVE_API_KEY} \
  -Body $requestData

Explanation

The POST request submits your optimization problem. The API immediately returns a job ID that you'll use to track progress.

6

Post and Poll Status

Submit the request and monitor progress until completion

Code Example

powershell
# Submit the request
$response = Invoke-RestMethod -Uri "https://plansolve.app/api/solve" \
  -Method POST \
  -Headers @{"Content-Type"="application/json"; "X-API-KEY"=$env:PLANSOLVE_API_KEY} \
  -Body $requestData

# Extract job ID
$jobId = $response.jobId
Write-Host "Job ID: $jobId"

# Poll for status every 5 seconds
do {
  $status = Invoke-RestMethod -Uri "https://plansolve.app/api/solve/$jobId" \
    -Method GET \
    -Headers @{"X-API-KEY"=$env:PLANSOLVE_API_KEY}
  
  Write-Host "Status: $($status.status)"
  
  if ($status.status -eq "COMPLETED") {
    Write-Host "Optimization completed!"
    break
  } elseif ($status.status -eq "FAILED") {
    Write-Host "Optimization failed!"
    exit 1
  }
  
  Start-Sleep -Seconds 5
} while ($true)

Explanation

Optimization is asynchronous and can take 30-60 seconds. Poll the status endpoint every 5 seconds until completion.

7

Process Results

Retrieve and use the optimized routes

Code Example

powershell
# Get the results
$results = Invoke-RestMethod -Uri "https://plansolve.app/api/solve/$jobId/result" \
  -Method GET \
  -Headers @{"X-API-KEY"=$env:PLANSOLVE_API_KEY}

# Display vehicle routes
Write-Host "Vehicle Routes:"
$results.vehicles | ForEach-Object {
    Write-Host "Vehicle $($_.id): $($_.visits.Count) visits, total driving time: $($_.totalDrivingTimeSeconds)s"
}

# Display visit details with timing
Write-Host "Visit Details:"
$results.visits | ForEach-Object {
    Write-Host "  $($_.name): arrive $($_.arrivalTime), service $($_.startServiceTime), depart $($_.departureTime)"
}

# Show visit sequence for a specific vehicle
Write-Host "Visit Sequence for Vehicle 1@2024-01-15:"
$vehicle = $results.vehicles | Where-Object { $_.id -eq "1@2024-01-15" }
$vehicle.visits | ForEach-Object { Write-Host $_ }

# Save results to file
$results | ConvertTo-Json -Depth 10 | Out-File -FilePath "results.json" -Encoding UTF8

Explanation

Results include two main sections: result.vehicles shows the visit order and driving times for each technician, while result.visits contains detailed timing information including arrival time, start service time, departure time, and driving time between visits. Use this data to update your dispatch system or mobile apps.

Complete Working Example

Here's a complete script you can run to test the entire workflow:

powershell
# Set your API key
 $env:PLANSOLVE_API_KEY="your-api-key-here"

 # Create request data
 $requestData = @{
     solver = "field_service"
     startDate = "2024-01-15"
     endDate = "2024-01-15"
     startDateTime = "2024-01-15T08:00:00"
     endDateTime = "2024-01-15T18:00:00"
     southwestCorner = @(40.7000, -74.0200)
     northeastCorner = @(40.8000, -73.9700)
     vehicles = @(
         @{
             id = "tech1"
             homeLocation = @(40.7128, -74.0060)
             skills = @("repair", "installation")
             shifts = @(
                 @{
                     id = "morning"
                     minStartTime = "2024-01-15T08:00:00"
                     maxEndTime = "2024-01-15T17:00:00"
                 }
             )
         }
     )
     visits = @(
         @{
             id = "visit1"
             name = "AC Repair - Downtown Office"
             location = @(40.7589, -73.9851)
             timeWindows = @(
                 @{
                     minStartTime = "2024-01-15T09:00:00"
                     maxEndTime = "2024-01-15T17:00:00"
                 }
             )
             serviceDuration = "PT60M"
             priority = "HIGH"
             requiredSkills = @("repair")
         }
     )
 } | ConvertTo-Json -Depth 10

 # Submit request
 Write-Host "Submitting optimization request..."
 $response = Invoke-RestMethod -Uri "https://plansolve.app/api/solve" -Method POST -Headers @{"Content-Type"="application/json"; "X-API-KEY"=$env:PLANSOLVE_API_KEY} -Body $requestData

 $jobId = $response.jobId
 Write-Host "Job ID: $jobId"

 # Poll status
 Write-Host "Polling for completion..."
 do {
     $status = Invoke-RestMethod -Uri "https://plansolve.app/api/solve/$jobId" -Method GET -Headers @{"X-API-KEY"=$env:PLANSOLVE_API_KEY}
     
     Write-Host "Status: $($status.status)"
     
     if ($status.status -eq "COMPLETED") {
         Write-Host "✅ Optimization completed!"
         break
     } elseif ($status.status -eq "FAILED") {
         Write-Host "❌ Optimization failed!"
         exit 1
     }
     
     Start-Sleep -Seconds 5
 } while ($true)

 # Get results
 Write-Host "Retrieving results..."
 $results = Invoke-RestMethod -Uri "https://plansolve.app/api/solve/$jobId/result" -Method GET -Headers @{"X-API-KEY"=$env:PLANSOLVE_API_KEY}

 Write-Host "🎯 Final Routes:"
 $results.vehicles | ForEach-Object {
     Write-Host "Technician $($_.id): $($_.visits.Count) visits, total driving time: $($_.totalDrivingTimeSeconds)s"
 }

 Write-Host "📋 Visit Details:"
 $results.visits | ForEach-Object {
     Write-Host "  - $($_.name) at $($_.arrivalTime)"
 }

 Write-Host "💾 Results saved to results.json"
 $results | ConvertTo-Json -Depth 10 | Out-File -FilePath "results.json" -Encoding UTF8

Understanding the Results

The API returns a structured response with two main sections: vehicles and visits. Here's what each contains:

Result Structure

json
{
   "southWestCorner": [51.45, -0.15],
   "northEastCorner": [51.55, -0.05],
   "startDateTime": "2024-01-15T08:00:00",
   "endDateTime": "2024-01-15T18:00:00",
   "vehicles": [
     {
       "id": "1@2024-01-15",
       "visits": ["1", "2", "3"],
       "totalDrivingTimeSeconds": 5143,
       "arrivalTime": "2024-01-15T15:59:38",
       "departureTime": "2024-01-15T08:00:00"
     }
   ],
   "visits": [
     {
       "id": "1",
       "name": "Task 1 - Day 1 Morning",
       "vehicle": "1@2024-01-15",
       "arrivalTime": "2024-01-15T08:16:11",
       "startServiceTime": "2024-01-15T09:00:00",
       "departureTime": "2024-01-15T09:30:00",
       "drivingTimeSecondsFromPreviousStandstill": 971
     }
   ]
 }

Vehicles Section

  • visits - Array of visit IDs in execution order
  • totalDrivingTimeSeconds - Total driving time for the day
  • arrivalTime - When the vehicle returns home
  • departureTime - When the vehicle leaves home

Visits Section

  • arrivalTime - When technician arrives at location
  • startServiceTime - When service actually begins
  • departureTime - When technician leaves location
  • drivingTimeSecondsFromPreviousStandstill - Travel time from previous stop
  • vehicle - Which technician is assigned

Ready to Build?

Start with this example and gradually add more vehicles and visits as you become familiar with the API.

Need help? Check out our comprehensive documentation and examples.