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

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
Step 1 of 7
Step 7 of 7
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"
  }]
}

What This Does

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"]
}

What This Does

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"]
    }
  ]
}

What This Does

This is your complete optimization request. The solver field must be 'field_service', and you need to specify the geographic bounds (southwestCorner and northeastCorner) that contain all your locations. The API will return a job ID for tracking.

4
Submit Request
Send your optimization request to the API

Code Example

POWERSHELL
$headers = @{
    "X-API-KEY" = "your-api-key-here"
    "Content-Type" = "application/json"
}

$body = @{
    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

$response = Invoke-RestMethod -Uri "https://api.plansolve.com/api/solve" -Method Post -Headers $headers -Body $body
$jobId = $response.jobId
Write-Host "Job submitted with ID: $jobId"

What This Does

Use PowerShell's Invoke-RestMethod to submit your request. The API will return a job ID that you'll use to track progress and retrieve results. Make sure to replace 'your-api-key-here' with your actual API key.

5
Check Job Status
Monitor the progress of your optimization job

Code Example

POWERSHELL
$statusResponse = Invoke-RestMethod -Uri "https://api.plansolve.com/api/solve/$jobId" -Method Get -Headers $headers
$status = $statusResponse.status
Write-Host "Job status: $status"

# Possible statuses: PENDING, RUNNING, COMPLETED, FAILED
if ($status -eq "COMPLETED") {
    Write-Host "Optimization completed successfully!"
} elseif ($status -eq "FAILED") {
    Write-Host "Optimization failed. Check the error details."
} else {
    Write-Host "Job is still processing. Status: $status"
}

What This Does

Poll the status endpoint to check if your optimization job has completed. The job will go through PENDING → RUNNING → COMPLETED states. For complex problems, this might take several minutes.

6
Retrieve Results
Download your optimized solution when the job completes

Code Example

POWERSHELL
if ($status -eq "COMPLETED") {
    $results = Invoke-RestMethod -Uri "https://api.plansolve.com/api/solve/$jobId/result" -Method Get -Headers $headers
    
    # Display the optimized routes
    Write-Host "Optimized Routes:" -ForegroundColor Green
    foreach ($vehicle in $results.vehicles) {
        Write-Host "Vehicle: $($vehicle.id)" -ForegroundColor Yellow
        Write-Host "Total driving time: $([math]::Round($vehicle.totalDrivingTimeSeconds / 60, 2)) minutes"
        Write-Host "Route: $($vehicle.visits -join ' → ')"
        Write-Host "Departure: $($vehicle.departureTime)"
        Write-Host "Return: $($vehicle.arrivalTime)"
    }
    
    # Save results to file
    $results | ConvertTo-Json -Depth 10 | Out-File -FilePath "optimization-results.json" -Encoding UTF8
    Write-Host "Results saved to optimization-results.json" -ForegroundColor Green
}

What This Does

Once the job completes, retrieve the full results. The API returns detailed information about each vehicle's route, including visit order, timing, and driving distances. You can save this to a file for further processing.

7
Complete Working Example
Put it all together in a single PowerShell script

Code Example

POWERSHELL
# Complete Field Service Optimization Script
$apiKey = "your-api-key-here"
$headers = @{
    "X-API-KEY" = $apiKey
    "Content-Type" = "application/json"
}

# Step 1: Create vehicles
$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"
            }
        )
    }
)

# Step 2: Create visits
$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")
    }
)

# Step 3: Create optimization request
$request = @{
    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 = $vehicles
    visits = $visits
}

# Step 4: Submit request
$body = $request | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Uri "https://api.plansolve.com/api/solve" -Method Post -Headers $headers -Body $body
$jobId = $response.jobId
Write-Host "Job submitted with ID: $jobId"

# Step 5: Monitor status
do {
    Start-Sleep -Seconds 10
    $statusResponse = Invoke-RestMethod -Uri "https://api.plansolve.com/api/solve/$jobId" -Method Get -Headers $headers
    $status = $statusResponse.status
    Write-Host "Job status: $status"
} while ($status -in @("PENDING", "RUNNING"))

# Step 6: Get results
if ($status -eq "COMPLETED") {
    $results = Invoke-RestMethod -Uri "https://api.plansolve.com/api/solve/$jobId/result" -Method Get -Headers $headers
    Write-Host "Optimization completed successfully!" -ForegroundColor Green
    
    # Display results
    foreach ($vehicle in $results.vehicles) {
        Write-Host "Vehicle: $($vehicle.id)" -ForegroundColor Yellow
        Write-Host "Route: $($vehicle.visits -join ' → ')"
    }
} else {
    Write-Host "Optimization failed with status: $status" -ForegroundColor Red
}

What This Does

This complete script demonstrates the entire workflow from creating vehicles and visits to retrieving optimized results. It includes error handling and status monitoring. You can use this as a template for your own implementations.

Understanding Your Results

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

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

  • visitsArray of visit IDs in execution order
  • totalDrivingTimeSecondsTotal driving time for the day
  • arrivalTimeWhen the vehicle returns home
  • departureTimeWhen the vehicle leaves home

Visits Section

  • arrivalTimeWhen technician arrives at location
  • startServiceTimeWhen service actually begins
  • departureTimeWhen technician leaves location
  • drivingTimeSecondsFromPreviousStandstillTravel time from previous stop
  • vehicleWhich 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.