API Documentation

vitaRoute API integration guide

Quick Start

The vitaRoute API is REST-based and works with JSON. All requests must be sent over HTTPS.

Base URL: https://api.vitaroute.ai
  1. Create a free account
  2. Generate an API key from the Dashboard
  3. Send your first optimization request

Authentication

All API requests require authentication via the X-Api-Key header.

X-Api-Key: vtr_live_xxxxxxxxxxxxxxxxxxxx

⚠️ Security Note

Do not include your API keys in source code. Use environment variables.

Endpoints

POST/api/optimization/optimize

Advanced route optimization. The most efficient routes are calculated by evaluating 20+ parameters with the RL-powered proprietary vitaRoute algorithm.

POST/api/route/calculate

Basic route calculation. Simple cluster-based route plan.

POST/api/route/cluster-stops

Clusters existing stops according to vehicle capacity.

Request Schema

FieldTypeDescription
facilityLatfloatFacility/depot latitude coordinate
facilityLngfloatFacility/depot longitude coordinate
totalCapacityintMaximum capacity per vehicle (default: 14)
vehicleCountintAlways 0 — vehicle count is auto-determined
maxWalkingint?Maximum walking distance (meters, default: 500)
maxDurationint?Maximum route duration (minutes, default: 90)
maxClusterDiameterKmfloatMaximum geographic diameter of stops in the same cluster (km, default: 25)
minSavingsKmfloatMinimum distance saving required to merge a stop (km, default: 0.3)
maxDetourFactorfloatMaximum detour ratio when adding a stop to an existing route (default: 0.6)
minDistrictPassengersintMinimum passengers required to create a district-specific route (default: 8)
tripDirectionstringTrip direction: 'to_facility' (inbound to depot) or 'from_facility' (outbound from depot)
arrivalTimeAtDepotstring?Vehicle arrival time at depot (ISO 8601 UTC). When provided, speed is calculated based on traffic profile; otherwise a fixed 28 km/h is used.
useDistanceMatrixbooleanWhether to use Google Maps Distance Matrix API for accurate road distances (default: false)
nodesNodeInput[]List of personnel/locations to optimize

NodeInput

FieldTypeDescription
idstringUnique personnel/location identifier
namestringPersonnel name
latitudefloatLatitude coordinate
longitudefloatLongitude coordinate
districtstring?District name (optional, for district rules)

Response Schema

{
  "routes": [
    {
      "routeId": "uuid",
      "routeName": "GEBZE 1",
      "totalDuration": 45,
      "totalDistance": 28500,
      "nodeCount": 14,
      "totalLoad": 14,
      "stops": [
        {
          "stopIndex": 0,
          "latitude": 40.8962,
          "longitude": 29.1882,
          "nodes": [
            { "id": "1", "name": "Ali Yilmaz" }
          ]
        }
      ],
      "routeCenter": {
        "latitude": 40.9,
        "longitude": 29.2
      }
    }
  ]
}

Rate Limits

PlanMonthly RequestsMax NodesConcurrent
Free5011
Starter1,0001005
Growth5,00050020
EnterpriseUnlimitedUnlimitedCustom

When the rate limit is exceeded, a 429 Too Many Requests response is returned. The Retry-After header specifies the wait time.

Error Codes

400

Bad Request

Invalid JSON or missing required field

401

Unauthorized

API key missing or invalid

403

Forbidden

Your plan limit has been exceeded

429

Too Many Requests

Rate limit exceeded

500

Internal Server Error

Server error, please contact support

Code Examples

curl

curl -X POST https://api.vitaroute.ai/api/optimization/optimize \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: vtr_live_your_key_here" \
  -d '{
    "facilityLat": 40.9139,
    "facilityLng": 29.1167,
    "totalCapacity": 16,
    "vehicleCount": 0,
    "maxWalking": 500,
    "maxDuration": 90,
    "maxClusterDiameterKm": 25,
    "minSavingsKm": 0.3,
    "maxDetourFactor": 0.6,
    "minDistrictPassengers": 8,
    "tripDirection": "to_facility",
    "arrivalTimeAtDepot": "2025-01-15T05:00:00Z",
    "useDistanceMatrix": false,
    "nodes": [
      { "id": "1", "name": "Ali Yilmaz", "latitude": 40.8962, "longitude": 29.1882, "district": "Kadikoy" },
      { "id": "2", "name": "Ayse Demir", "latitude": 40.9278, "longitude": 29.3125, "district": "Gebze" }
    ]
  }'

python

import requests

response = requests.post(
    "https://api.vitaroute.ai/api/optimization/optimize",
    headers={
        "Content-Type": "application/json",
        "X-Api-Key": "vtr_live_your_key_here"
    },
    json={
        "facilityLat": 40.9139,
        "facilityLng": 29.1167,
        "totalCapacity": 16,
        "vehicleCount": 0,
        "maxWalking": 500,
        "maxDuration": 90,
        "maxClusterDiameterKm": 25,
        "minSavingsKm": 0.3,
        "maxDetourFactor": 0.6,
        "minDistrictPassengers": 8,
        "tripDirection": "to_facility",
        "arrivalTimeAtDepot": "2025-01-15T05:00:00Z",
        "useDistanceMatrix": False,
        "nodes": [
            {"id": "1", "name": "Ali Yilmaz", "latitude": 40.8962, "longitude": 29.1882}
        ]
    }
)

data = response.json()
for route in data["routes"]:
    print(f"{route['routeName']}: {route['nodeCount']} stops, {route['totalDuration']} min")

javascript

const response = await fetch(
  "https://api.vitaroute.ai/api/optimization/optimize",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-Api-Key": "vtr_live_your_key_here",
    },
    body: JSON.stringify({
      facilityLat: 40.9139,
      facilityLng: 29.1167,
      totalCapacity: 16,
      vehicleCount: 0,
      maxWalking: 500,
      maxDuration: 90,
      maxClusterDiameterKm: 25,
      minSavingsKm: 0.3,
      maxDetourFactor: 0.6,
      minDistrictPassengers: 8,
      tripDirection: "to_facility",
      arrivalTimeAtDepot: "2025-01-15T05:00:00Z",
      useDistanceMatrix: false,
      nodes: [
        { id: "1", name: "Ali Yilmaz", latitude: 40.8962, longitude: 29.1882 },
      ],
    }),
  }
);

const { routes } = await response.json();
routes.forEach(route => {
  console.log(`${route.routeName}: ${route.nodeCount} stops`);
});

C#

using System.Net.Http.Json;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Api-Key", "vtr_live_your_key_here");

var payload = new {
    facilityLat = 40.9139,
    facilityLng = 29.1167,
    totalCapacity = 16,
    vehicleCount = 0,
    maxWalking = 500,
    maxDuration = 90,
    maxClusterDiameterKm = 25,
    minSavingsKm = 0.3,
    maxDetourFactor = 0.6,
    minDistrictPassengers = 8,
    tripDirection = "to_facility",
    arrivalTimeAtDepot = "2025-01-15T05:00:00Z",
    useDistanceMatrix = false,
    nodes = new[] {
        new { id = "1", name = "Ali Yilmaz", latitude = 40.8962, longitude = 29.1882 }
    }
};

var response = await client.PostAsJsonAsync(
    "https://api.vitaroute.ai/api/optimization/optimize",
    payload
);

var result = await response.Content.ReadFromJsonAsync<RouteResponse>();

Integration API (ERP Integration)

An API designed for managing vitaRoute end-to-end from your own interface (e.g. an ERP system). Create and update project, shift, and passenger records, read finalized route plans, and write back edits you make — all without ever touching the extranet UI.

Base URL: https://api.vitaroute.ai/api/integration

Uses the same authentication (X-Api-Key); all endpoints live under https://api.vitaroute.ai/api/integration.

All PUT (update) requests are PARTIAL — only fields you send in the body change; omitted fields keep their current value.

When updating a plan, do NOT send route geometry (savedPolyline) or distance/duration (savedStats) — vitaRoute computes these itself from your stop order via Google Directions, so the map always shows a valid, real road path.

Projects

Create, list, update, and delete projects. An ERP should store the id of the vitaRoute project matching its own customer record here.

GET/api/integration/projects

Lists all projects owned by the API key.

POST/api/integration/projects

Creates a new project (facility location, optimization model, trip info).

PUT/api/integration/projects/{projectId}

Partially updates a project — only the fields provided change.

DELETE/api/integration/projects/{projectId}

Permanently deletes a project and all its data (passengers, shifts, runs, plans). Irreversible.

FieldTypeDescription
namestringProject name
facilityLatfloatFacility latitude
facilityLngfloatFacility longitude
descriptionstring?Description (optional)
countryCodestring?Country code, e.g. "TR" (optional)
iconstring?Facility icon key (optional)
optimizationModelstring"personnel" (staff transport) | "school" (school transport)
passengerModestring"fixed" (fixed trips) | "shift" (shift-based) — only meaningful in personnel model
tripsTrip[]List of trips (time+direction). At least one is required in fixed mode; ignored in shift mode.

Shifts

Full CRUD for shift records that define facility entry/exit times in shift-based projects.

GET/api/integration/shifts?projectId=

Lists all shifts for a project.

POST/api/integration/shifts

Adds a new shift (at least one of entry/exit time is required).

PUT/api/integration/shifts/{shiftId}

Partially updates a shift.

DELETE/api/integration/shifts/{shiftId}

Deletes a shift.

FieldTypeDescription
projectIdstringId of the project to add the shift to
namestringShift name, e.g. "Morning"
entryTimestring?Facility entry time, "HH:mm" (optional)
exitTimestring?Facility exit time, "HH:mm" (optional)
nextDayExitbooleantrue = exit is next day (only meaningful when exitTime is given)

Passengers

Full CRUD for passenger/student/employee records. The employee_no field is an optional natural key so your ERP can match records by its own registry/student number.

GET/api/integration/passengers?projectId=

Lists all passengers for a project.

POST/api/integration/passengers

Adds a new passenger (name and location are required).

PUT/api/integration/passengers/{nodeId}

Partially updates a passenger.

DELETE/api/integration/passengers/{nodeId}

Deletes a passenger.

FieldTypeDescription
projectIdstringId of the project to add the passenger to
namestringPassenger name
latitudefloatLatitude
longitudefloatLongitude
employeeNostring?Registry/student number — natural key for matching your own records (optional)
departmentstring?Department (optional)
genderstring?"male" | "female" (optional)
specialNeedsbooleanSpecial needs flag (default: false)
addressstring?Address text (optional)
citystring?City (optional)
districtstring?District (optional)

Plan Transfer

Read finalized route plans filtered by project/date/shift/direction; write back the stop order and passenger assignment you edited.

GET/api/integration/plan?projectId=&dateFrom=&dateTo=&shiftName=&direction=

Returns finalized route plan(s) matching project/date range/shift/direction filters — including routes, stops, passengers, distance and duration — in full.

PUT/api/integration/plan/{runId}

Overwrites a run's route/stop/passenger data with the edits made on the ERP side. Route geometry is recomputed by vitaRoute.

result[] — Route

FieldTypeDescription
routeNamestring?Route name, e.g. "Route 1"
colorstring?Display color on the map, hex (optional)
stopsStop[]Stops, IN ROUTE ORDER

stops[] — Stop

FieldTypeDescription
latfloatStop latitude
lngfloatStop longitude
stopNamestring?Stop name (optional)
passengersPassenger[]Passengers assigned to this stop

passengers[] — Passenger

FieldTypeDescription
idstringExisting passenger id (must match the one from the GET response exactly) — REQUIRED
namestring?Passenger name (display only)

Integration API Examples

GET /projects

curl https://api.vitaroute.ai/api/integration/projects \
  -H "X-Api-Key: vtr_live_your_key_here"

POST /passengers

curl -X POST https://api.vitaroute.ai/api/integration/passengers \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: vtr_live_your_key_here" \
  -d '{
    "projectId": "b3f1c2a4-...",
    "name": "Ali Yilmaz",
    "latitude": 40.8962,
    "longitude": 29.1882,
    "employeeNo": "EMP-00123"
  }'

GET /plan

curl "https://api.vitaroute.ai/api/integration/plan?projectId=b3f1c2a4-...&shiftName=Sabah&direction=to_facility" \
  -H "X-Api-Key: vtr_live_your_key_here"

PUT /plan/{runId}

curl -X PUT https://api.vitaroute.ai/api/integration/plan/9e7d0f21-... \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: vtr_live_your_key_here" \
  -d '{
    "result": [
      {
        "routeName": "Hat 1",
        "color": "#1E40AF",
        "stops": [
          {
            "lat": 40.8962, "lng": 29.1882, "stopName": "Kadikoy Iskele",
            "passengers": [{ "id": "3f9a...", "name": "Ali Yilmaz" }]
          }
        ]
      }
    ]
  }'
# Not: savedPolyline / savedStats göndermezsiniz — vitaRoute rota
# geometrisini durak sırasından kendisi hesaplar.