Перейти к основному содержимому

Примеры

Ниже приведено описание параметров из Справочника API и примеры использования их при отправке запросов к TSP API.

Параметры точек

Для каждой точки маршрута вы можете дополнительно:

Типы точек

У каждой точки в массиве waypoints может быть один из типов (type):

  • delivery (по умолчанию) — точка доставки груза. Курьер привозит груз в эту точку.
  • pickup — точка забора груза. Курьер забирает груз из этой точки.
  • agent — текущее местоположение курьера. Используется, чтобы задать начальную позицию курьера как обычную точку (вместо указания start_at в параметрах курьера).

Например, чтобы задать точку забора груза:

{
"waypoints": [
{
"id": "wp-pickup-1",
"point": {
"lat": 54.994814,
"lon": 82.87837
},
"type": "pickup",
"shipment_size": {
"weight_kg": 10
}
}
]
}

Временные окна посещения точки

Временны́е окна — это допустимые временные отрезки посещения точки. Виды временных окон:

  • Жёсткое (hard_time_window): если курьер не попал на точку в указанный временной отрезок, она исключается из расчёта маршрута.
  • Мягкое с жёстким ограничением (time_window + hard_time_window): курьер может опоздать относительно мягкого окна, но не может выйти за пределы жёсткого. Мягкое временное окно означает, что точка остаётся в расчёте маршрута даже при опоздании курьера.

Время задаётся в одном из форматов (UTC либо с указанием смещения в соответствии с ISO 8601):

  • hh:mm-hh:mm (например, 08:00-10:00);
  • hh:mm:ss-hh:mm:ss (например, 08:00:30-10:00:30);
  • ISO 8601 (например, 2025-09-16T16:00:00+03:00/2025-09-16T19:00:00+03:00).

Например, чтобы задать жёсткое временное окно для точки и посетить её с 15 часов 07 минут до 17 часов 54 минут:

{
"waypoints": [
{
"id": "wp-0",
"point": {
"lat": 54.994814,
"lon": 82.87837
},
"time_windows": [
{
"hard_time_window": "15:07-17:54"
}
]
}
]
}

Например, чтобы задать мягкое временное окно с жёсткими границами (курьер может опоздать, но не более чем на 30 минут):

{
"waypoints": [
{
"id": "wp-0",
"point": {
"lat": 54.994814,
"lon": 82.87837
},
"time_windows": [
{
"time_window": "15:07-17:54",
"hard_time_window": "14:37-18:24"
}
]
}
]
}

Продолжительность работ в точке

Вы можете указать отрезок времени, который курьер проведёт в точке (например, чтобы оформить и забрать груз), с помощью параметра service_duration_s. Продолжительность задаётся в секундах.

Например, задержаться в точке на 10 минут:

{
"waypoints": [
{
"id": "wp-0",
"point": {
"lat": 54.994814,
"lon": 82.87837
},
"service_duration_s": 600
}
]
}

Получение заказа на складе

Для точек доставки (type: "delivery") можно указать параметры, связанные с получением заказа на складе:

  • depot_ready_time — время, когда заказ будет готов к выдаче на складе. Курьер не сможет забрать заказ раньше этого времени.
  • depot_expiring_time — крайний срок, до которого курьер должен забрать заказ на складе.
  • depot_duration_s — время, которое займёт загрузка или выгрузка на складе (в секундах). Учитывается в расчёте маршрута отдельно от service_duration_s самой точки.

Время задаётся в одном из форматов (UTC либо с указанием смещения в соответствии с ISO 8601):

  • hh:mm (например, 08:00);
  • hh:mm:ss (например, 08:00:00);
  • ISO 8601 (например, 2025-09-16T16:00:00+03:00).

Например, заказ будет готов на складе к 10:00, забрать его нужно до 12:00, а загрузка займёт 5 минут:

{
"depots": [
{
"id": "depot-0",
"point": { "lat": 55.751244, "lon": 37.618423 },
"time_windows": { "hard_time_window": "08:00-20:00" }
}
],
"waypoints": [
{
"id": "wp-0",
"point": { "lat": 54.994814, "lon": 82.87837 },
"type": "delivery",
"depot_ids": ["depot-0"],
"depot_ready_time": "10:00",
"depot_expiring_time": "12:00",
"depot_duration_s": 300,
"service_duration_s": 600
}
]
}

В этом примере:

  • курьер может забрать заказ на складе depot-0 не раньше 10:00 и не позже 12:00;
  • загрузка на складе займёт 5 минут (300 секунд);
  • вручение заказа в точке wp-0 займёт 10 минут (600 секунд).

Связанная точка доставки

Параметр delivery_to позволяет связать точку забора груза (type: "pickup") с конкретной точкой доставки. Это гарантирует, что груз, забранный в точке pickup, будет доставлен в указанную точку, и обе точки посетит один и тот же курьер.

Например, забрать груз из точки wp-pickup и доставить его в точку wp-delivery:

{
"waypoints": [
{
"id": "wp-pickup",
"point": { "lat": 55.751244, "lon": 37.618423 },
"type": "pickup",
"delivery_to": "wp-delivery",
"shipment_size": {
"weight_kg": 25
}
},
{
"id": "wp-delivery",
"point": { "lat": 55.773128, "lon": 37.597472 },
"type": "delivery",
"shipment_size": {
"weight_kg": 25
}
}
],
"agents": [
{
"id": "agent-0",
"capacity": {
"weight_kg": 100
},
"cost": {}
}
]
}

В этом примере алгоритм гарантирует, что:

  • точка wp-pickup будет посещена раньше, чем wp-delivery;
  • обе точки попадут в маршрут одного курьера;
  • если одна из связанных точек будет исключена из задачи, другая точка также будет исключена;
  • вес 25 кг будет учтён при расчёте загрузки курьера: он появится после забора и исчезнет после доставки.

Штраф за непосещение точки

Вы можете установить штраф за непосещение точки с помощью параметра penalties.drop. Например:

{
"waypoints": [
{
"id": "wp-important",
"point": { "lat": 54.994814, "lon": 82.87837 },
"time_windows": [{ "hard_time_window": "10:00-12:00" }],
"penalties": {
"drop": 6000
}
},
]
}

Алгоритм сравнивает размер штрафа и стоимость работы курьера при оптимизации. Если штраф за непосещение точки выше стоимости привлечения дополнительного курьера, алгоритм предпочтёт задействовать ещё одного курьера; если ниже — исключит точку из маршрута. Чтобы алгоритм корректно сравнил размер штрафа и стоимость работы курьера, указывайте эти значения в одинаковых единицах.

Параметры складов

Склады задаются в отдельном массиве depots на верхнем уровне запроса. В отличие от обычных точек (waypoints), склады не участвуют в оптимизации порядка посещения — они служат начальными и конечными точками курьеров.

Склады:

  • могут иметь собственное расписание работы (time_window);
  • имеют время обслуживания (service_duration_s), которое учитывается при расчёте маршрута;
  • поддерживают штрафы за раннее или позднее обслуживание (penalties).

Например, чтобы задать склад с расписанием работы и временем на загрузку:

{
"depots": [
{
"id": "depot-0",
"point": {
"lat": 55.751244,
"lon": 37.618423
},
"service_duration_s": 900,
"time_window":
{
"hard_time_window": "08:00-20:00"
}
}
],
"agents": [
{
"id": "agent-0",
"start_at": "depot-0",
"finish_at": "depot-0",
"cost": {}
}
],
"waypoints": [...]
}

Если точка доставки может обслуживаться с нескольких складов, укажите их идентификаторы в параметре depot_ids точки. Алгоритм выберет оптимальный склад:

{
"depots": [
{
"id": "depot-north",
"point": { "lat": 55.85, "lon": 37.60 },
"time_window": { "hard_time_window": "08:00-18:00" }
},
{
"id": "depot-south",
"point": { "lat": 55.65, "lon": 37.62 },
"time_window": { "hard_time_window": "08:00-18:00" }
}
],
"waypoints": [
{
"id": "wp-0",
"point": { "lat": 55.75, "lon": 37.61 },
"type": "delivery",
"depot_ids": ["depot-north", "depot-south"]
}
]
}

Параметры маршрутов

Вы можете указать дополнительные параметры построения маршрута:

Кратчайший по времени

По умолчанию прокладывается кратчайший по времени автомобильный маршрут с учётом текущих пробок. Чтобы указать тип маршрута явно, добавьте в запрос поле route_type:

{
"waypoints": [...],
"agents": [...],
"options": {
"route_type": "jam" // автомобильный маршрут по текущим пробкам
}
}

Вместо текущих пробок можно использовать статистическую информацию по пробкам. Для этого укажите тип маршрута statistics и дату в поле date:

{
"waypoints": [...],
"agents": [...],
"options": {
"route_type": "statistics", // автомобильный маршрут на основе статистических данных по пробкам...
"date": "2020-05-15", // ...на 15 мая 2020 года
"time_zone": "UTC"
}
}

Если параметр date не указан, используется текущая дата.

Пример расчёта обхода одних и тех же точек с учётом текущих пробок (слева) и с учётом статистической информации по пробкам (справа):

Расчёт с учётом пробок  Расчёт по статистике пробок

Кратчайший по расстоянию

Чтобы построить самый короткий маршрут, даже если он не является оптимальным по времени из-за пробок, укажите тип shortest:

{
"waypoints": [...],
"agents": [...],
"options": {
"route_type": "shortest"
}
}

Для автомобиля

По умолчанию маршрут строится для проезда на легковом автомобиле. Чтобы указать тип транспорта явно, используйте параметр routing_type со значением driving:

{
"waypoints": [...],
"agents": [...],
"options": {
"routing_type": "driving" // автомобиль
}
}

Для грузового транспорта

Чтобы построить маршрут для грузового транспорта:

  1. Укажите параметр routing_type со значением truck:

    {
    "waypoints": [...],
    "options": {
    "routing_type": "truck" // грузовой транспорт
    }
    }
  2. (Дополнительно) Укажите характеристики груза и транспорта при помощи параметра truck_params. Если характеристика не указана, используется значение по умолчанию:

    {
    "waypoints": [...],
    "options": {
    "routing_type": "truck",
    "truck_params": {
    "max_perm_mass": 10,
    "mass": 9,
    "axle_load": 4,
    "height": 3.2,
    "width": 2.5,
    "length": 7,
    "dangerous_cargo": true,
    "explosive_cargo": true
    }
    }
    }
  3. Если маршрут проходит через пропускные зоны, где движение грузового транспорта ограничено:

    1. Получите список всех действующих пропусков для грузового транспорта: отправьте GET-запрос на /truck_passes/1.0.0/global:

      curl --location --request GET 'http://routing.api.2gis.com/truck_passes/1.0.0/global?key=API_KEY' \
      --header 'Accept: application/json'

      В ответе будут перечислены актуальные пропускные зоны и ID пропусков.

    2. Укажите ID пропусков при помощи параметра pass_zone_pass_ids при отправке запроса к TSP API:

      {
      "waypoints": [...],
      "options": {
      "routing_type": "truck",
      "pass_zone_pass_ids": [4, 3, 2]
      }
      }

Для велосипедов

Чтобы построить велосипедный маршрут, укажите параметр routing_type со значением bicycle:

{
"waypoints": [...],
"agents": [...],
"options": {
"routing_type": "bicycle" // велосипедный маршрут
}
}

Для самокатов

Чтобы построить самокатный маршрут, укажите параметр routing_type со значением scooter:

{
"waypoints": [...],
"agents": [...],
"options": {
"routing_type": "scooter" // самокатный маршрут
}
}

Для пешеходов

Чтобы построить пешеходный маршрут, укажите параметр routing_type со значением walking:

{
"waypoints": [...],
"agents": [...],
"options": {
"routing_type": "walking" // пешеходный маршрут
}
}

Высота маршрута

Чтобы получить в ответе информацию о высоте пешеходного или велосипедного маршрута, добавьте в запрос поле need_altitudes со значением true:

{
"waypoints": [...],
"agents": [...],
"options": {
"routing_type": "walking", // или "routing_type": "bicycle"
"need_altitudes": true
}
}

Ответ содержит JSON-объект, в котором указана информация о высоте маршрута:

{
"routes": [
{
...
"altitudes_info": {
"elevation_gain": 0,
"elevation_loss": 0,
"max_altitude": 0,
"min_altitude": 0,
"max_road_angle": 0
}
},
...
]
}

Где:

  • elevation_gain — суммарное увеличение высоты в см;
  • elevation_loss — суммарное снижение высоты в см;
  • max_altitude — максимальная высота над уровнем моря в см;
  • min_altitude — минимальная высота над уровнем моря в см;
  • max_road_angle — максимальный угол наклона.

Начальные маршруты

Если часть маршрутов уже спланирована или курьеры уже в пути, вы можете передать начальные маршруты в массиве initial_routes. Алгоритм возьмёт за основу переданную последовательность точек и оптимизирует её, добавляя оставшиеся точки.

Каждый элемент initial_routes — это объект маршрута со следующими обязательными полями:

  • agent_id — идентификатор курьера.
  • run_number — номер рейса (начиная с 0).
  • route — массив шагов маршрута. Каждый шаг содержит:
    • arrival_time — время прибытия (ISO 8601).
    • departure_time — время отправления (ISO 8601).
    • node — узел маршрута с типом (depot, waypoint) и содержимым (value).
    • waiting_duration_s — время ожидания в секундах.
    • transit_duration_s — время в пути от предыдущей точки в секундах.
    • transit_distance_m — расстояние от предыдущей точки в метрах.

Например, курьер agent-0 уже в пути и должен посетить две точки в заданном порядке:

request.json
{
"initial_routes": [
{
"agent_id": "agent-0",
"run_number": 0,
"route": [
{
"arrival_time": "2025-09-16T09:00:00+03:00",
"departure_time": "2025-09-16T09:00:00+03:00",
"node": {
"type": "depot",
"value": { "depot_id": "depot-0", "delivery_to": "wp-1" }
},
"waiting_duration_s": 0,
"transit_duration_s": 0,
"transit_distance_m": 0
},
{
"arrival_time": "2025-09-16T09:15:00+03:00",
"departure_time": "2025-09-16T09:25:00+03:00",
"node": {
"type": "waypoint",
"value": { "waypoint_id": "wp-1" }
},
"waiting_duration_s": 0,
"transit_duration_s": 900,
"transit_distance_m": 5000
},
{
"arrival_time": "2025-09-16T09:40:00+03:00",
"departure_time": "2025-09-16T09:50:00+03:00",
"node": {
"type": "waypoint",
"value": { "waypoint_id": "wp-2" }
},
"waiting_duration_s": 0,
"transit_duration_s": 900,
"transit_distance_m": 4500
}
]
}
],
"depots": [
{
"id": "depot-0",
"point": { "lat": 55.751244, "lon": 37.618423 },
"time_window": { "hard_time_window": "08:00-20:00" }
}
],
"waypoints": [
{
"id": "wp-1",
"point": { "lat": 55.773128, "lon": 37.597472 },
"type": "delivery",
"depot_ids": ["depot-0"]
},
{
"id": "wp-2",
"point": { "lat": 55.790278, "lon": 37.558333 },
"type": "delivery",
"depot_ids": ["depot-0"]
},
{
"id": "wp-3",
"point": { "lat": 55.733333, "lon": 37.625000 },
"type": "delivery",
"depot_ids": ["depot-0"]
}
],
"agents": [
{
"id": "agent-0",
"start_at": "depot-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "08:00-18:00" }],
"cost": {}
}
],
"options": {}
}

В этом примере:

  • Курьер agent-0 начинает со склада depot-0 в 9:00, забирает заказ для точки wp-1, затем посещает wp-1 (прибытие в 9:15) и wp-2 (прибытие в 9:40).
  • Точка wp-3 не входит в начальный маршрут — алгоритм определит, куда её вставить для оптимального результата.

Расчёт длины маршрута

Ответ содержит данные о продолжительности маршрута в поле result:

{
"task_id": "...",
"status": {
"status": "Done",
"queued": "2025-09-16T08:00:00+03:00",
"completed": "2025-09-16T08:00:10+03:00"
},
"result": {
"metrics": {
"total_duration_s": 14244, // общее время в пути всех курьеров (в секундах)
"total_distance_m": 95634 // общая протяжённость пути всех курьеров (в метрах)
},
"routes": [
{
"agent_id": "agent-0",
"run_number": 1,
"duration_s": 7713, // продолжительность маршрута курьера в секундах
"distance_m": 45818, // протяжённость маршрута курьера в метрах
"route": [
{
"arrival_time": "2025-09-16T09:12:01+03:00",
"departure_time": "2025-09-16T09:22:01+03:00",
"node": {
"type": "waypoint",
"value": { "waypoint_id": "wp-1" }
},
"transit_duration_s": 4321, // время в пути до точки
"transit_distance_m": 33125, // протяжённость пути до точки
"waiting_duration_s": 0
},
...
]
},
...
],
"dropped_waypoints": [],
"dropped_agents": []
}
}

Где:

  • duration_s и distance_m — время в пути и длина маршрута каждого курьера.
  • total_duration_s и total_distance_m — общее время в пути и длина маршрута всех курьеров.
  • transit_duration_s и transit_distance_m — время в пути и длина маршрута до конкретной точки.
  • arrival_time и departure_time — время прибытия и отправления в формате ISO 8601.

Параметры курьеров

Для каждого курьера вы можете дополнительно настроить:

Начальная и конечная точка

Начальная и конечная точки не участвуют в оптимизации маршрута курьера. В качестве начальной или конечной точки можно указать идентификатор склада или обычной точки из массива waypoints.

Начальную точку (start_at) нужно указать для каждого курьера. Конечную точку (finish_at) указывать необязательно: в этом случае алгоритм подберёт оптимальное место окончания в текущей задаче.

Рабочие смены

Чтобы указать время, в которое курьер может посещать точки, используйте параметр shifts. Каждая смена задаётся временным окном. Например, чтобы задать смену курьера с 14:00 до 15:00:

{
"agents": [
{
"id": "agent-0",
"start_at": "wp-1",
"shifts": [
{
"id": "shift-1",
"hard_time_window": "14:00-15:00"
}
],
"cost": {}
}
]
}

Ограничение количества точек

Чтобы ограничить максимальное количество посещаемых точек для курьера, используйте параметр max_waypoints. Например, чтобы ограничить количество точек до 5:

{
"agents": [
{
"id": "agent-0",
"start_at": "wp-1",
"max_waypoints": 5,
"cost": {}
}
]
}

Ограничение длительности маршрута

Чтобы ограничить продолжительность работы курьера на маршруте, используйте параметры:

  • max_travel_time — максимальное время в пути в секундах;
  • max_distance — максимальная дистанция в метрах.

Например, чтобы ограничить время в пути курьера до 2 часов (7200 секунд) и дистанцию до 50 км (50000 метров):

{
"agents": [
{
"id": "agent-0",
"start_at": "wp-1",
"max_travel_time": 7200,
"max_distance": 50000,
"cost": {}
}
]
}

Стоимость работы

Параметр cost определяет стоимость работы курьера и влияет на оптимизацию: алгоритм минимизирует суммарную стоимость всех маршрутов.

Доступные параметры:

  • fixed — фиксированная стоимость за работу курьера;
  • hour — стоимость за час работы;
  • km — стоимость за километр пробега.

Например, чтобы настроить стоимость работы курьера с высокой ставкой за километр и фиксированной стоимостью:

{
"agents": [
{
"id": "agent-0",
"start_at": "wp-0",
"shifts": [
{
"id": "shift-1",
"hard_time_window": "08:00-18:00"
}
],
"cost": {
"fixed": 5000,
"hour": 200,
"km": 15
}
}
]
}

Алгоритм сравнивает стоимость работы курьера и штраф за непосещение точки. Чем выше стоимость работы курьера относительно штрафа за непосещение точки, тем вероятнее алгоритм будет исключать точки из маршрута вместо добавления нового курьера, и наоборот. Чтобы алгоритм корректно сравнил размер штрафа и стоимость работы курьера, указывайте эти значения в одинаковых единицах.

«Волны» курьеров

Если у груза есть ограниченное время жизни, за которое нужно успеть его забрать и доставить (например, продукты питания или медикаменты), вы можете задать волны курьеров. Каждая волна представляет собой группу курьеров с одинаковой рабочей сменой.

Например, время жизни груза — два часа. Курьеры должны успеть забрать его из трёх точек и доставить в целевую точку за это время. Для расчёта маршрута создайте несколько волн курьеров с разными сменами (параметр shifts). Например, если склад работает с 10:00 до 19:00, создайте восемь волн курьеров с разными диапазонами рабочего времени: 10:00-12:00, 11:00-13:00, 12:00-14:00 и т. д. Чтобы создать волны, каждая из которых содержит три курьера:

request.json
{
"agents": [
{
"id": "agent-0",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "10:00-12:00" }],
"cost": {}
},
{
"id": "agent-1",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "10:00-12:00" }],
"cost": {}
},
{
"id": "agent-2",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "10:00-12:00" }],
"cost": {}
},
{
"id": "agent-3",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "11:00-13:00" }],
"cost": {}
},
{
"id": "agent-4",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "11:00-13:00" }],
"cost": {}
},
{
"id": "agent-5",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "11:00-13:00" }],
"cost": {}
},
{
"id": "agent-6",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "12:00-14:00" }],
"cost": {}
},
{
"id": "agent-7",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "12:00-14:00" }],
"cost": {}
},
{
"id": "agent-8",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "12:00-14:00" }],
"cost": {}
},
{
"id": "agent-9",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "13:00-15:00" }],
"cost": {}
},
{
"id": "agent-10",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "13:00-15:00" }],
"cost": {}
},
{
"id": "agent-11",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "13:00-15:00" }],
"cost": {}
},
{
"id": "agent-12",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "14:00-16:00" }],
"cost": {}
},
{
"id": "agent-13",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "14:00-16:00" }],
"cost": {}
},
{
"id": "agent-14",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "14:00-16:00" }],
"cost": {}
},
{
"id": "agent-15",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "15:00-17:00" }],
"cost": {}
},
{
"id": "agent-16",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "15:00-17:00" }],
"cost": {}
},
{
"id": "agent-17",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "15:00-17:00" }],
"cost": {}
},
{
"id": "agent-18",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "16:00-18:00" }],
"cost": {}
},
{
"id": "agent-19",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "16:00-18:00" }],
"cost": {}
},
{
"id": "agent-20",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "16:00-18:00" }],
"cost": {}
},
{
"id": "agent-21",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "17:00-19:00" }],
"cost": {}
},
{
"id": "agent-22",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "17:00-19:00" }],
"cost": {}
},
{
"id": "agent-23",
"start_at": "wp-0",
"finish_at": "wp-0",
"shifts": [{ "id": "shift-1", "hard_time_window": "17:00-19:00" }],
"cost": {}
}
],
"waypoints": [
{
"id": "wp-0",
"point": {
"lat": 55.65256537472504,
"lon": 37.61882148499814
},
"time_windows": [
{
"hard_time_window": "10:00-19:00"
}
],
"service_duration_s": 600
},
{
"id": "wp-1",
"point": {
"lat": 55.721459289645324,
"lon": 37.449670621924085
},
"service_duration_s": 600
},
{
"id": "wp-2",
"point": {
"lat": 55.776325064840734,
"lon": 37.47788257797436
},
"service_duration_s": 600
},
{
"id": "wp-3",
"point": {
"lat": 55.74848713779916,
"lon": 37.655522514579175
},
"service_duration_s": 600
},
{
"id": "wp-4",
"point": {
"lat": 55.720542763421236,
"lon": 37.70352750313026
},
"service_duration_s": 600
}
],
"options": {}
}

Ответ содержит список маршрутов для каждого курьера и общие метрики. Одна из точек исключена из маршрута, т. к. курьеры из первой волны не успеют посетить её и доставить груз в отведённое время:

response.json
{
"task_id": "...",
"status": {
"status": "Done",
"queued": "...",
"completed": "..."
},
"result": {
"metrics": {
"total_duration_s": 13796,
"total_distance_m": 80577
},
"routes": [
{
"agent_id": "agent-0",
"run_number": 1,
"duration_s": 6601,
"distance_m": 38538,
"route": [
{
"arrival_time": "2025-09-16T10:42:09+03:00",
"departure_time": "2025-09-16T10:52:09+03:00",
"node": {
"type": "waypoint",
"value": { "waypoint_id": "wp-4" }
},
"transit_duration_s": 2529,
"transit_distance_m": 18153,
"waiting_duration_s": 0
},
{
"arrival_time": "2025-09-16T11:19:24+03:00",
"departure_time": "2025-09-16T11:29:24+03:00",
"node": {
"type": "waypoint",
"value": { "waypoint_id": "wp-3" }
},
"transit_duration_s": 1636,
"transit_distance_m": 6967,
"waiting_duration_s": 0
}
]
},
{
"agent_id": "agent-1",
"run_number": 1,
"duration_s": 7195,
"distance_m": 42039,
"route": [
{
"arrival_time": "2025-09-16T11:02:07+03:00",
"departure_time": "2025-09-16T11:12:07+03:00",
"node": {
"type": "waypoint",
"value": { "waypoint_id": "wp-1" }
},
"transit_duration_s": 3727,
"transit_distance_m": 26400,
"waiting_duration_s": 0
}
]
}
],
"dropped_waypoints": [
{
"id": "wp-2",
"reason": "failed_time"
}
],
"dropped_agents": []
}
}

Навыки

Если для выполнения работ на точке курьер должен обладать определёнными навыками, вы можете указать их в параметрах курьера и точки:

  • Укажите навыки курьера в массиве tags в параметрах курьера (массив agents). Если для курьера не заданы навыки, он может посещать только те точки, для работы в которых они не нужны.

  • Укажите навыки для работы в точке, в массиве required_tags в параметрах точки (массив waypoints). Точку могут посетить только курьеры со всеми необходимыми навыками. Если для точки не заданы навыки, её может посетить любой курьер.

В качестве навыка используется произвольная строка.

Например, для работы на некоторых точках может понадобиться навык «работа с хрупким грузом» (fragile). Чтобы указать, для каких точек необходим этот навык и какие курьеры им обладают, укажите его в параметрах курьера и точки:

{
"agents": [
{
"id": "agent-0",
"start_at": "wp-0",
"tags": ["fragile"], // курьер обладает навыком
"cost": {}
},
{
"id": "agent-1",
"start_at": "wp-0",
"cost": {}
// курьер не обладает специальными навыками
}
],
"waypoints": [
{
"id": "wp-1",
"point": {
"lat": 54.994814,
"lon": 82.87837
},
"required_tags": ["fragile"] // для работы в точке нужен навык
},
{
"id": "wp-2",
"point": {
"lat": 54.992333,
"lon": 82.87824
}
// для работы в точке не нужны специальные навыки
}
]
}

В примере выше курьер agent-0 сможет посетить обе точки, а курьер agent-1 — только точку wp-2.

Перевозка грузов

Чтобы в рамках маршрута контролировать, сколько груза курьер доставит в точку или заберёт из неё, укажите параметры:

  • Вместимость курьера: сколько груза он может перевозить.

    Например, грузоподъёмность курьера — 100 кг:

    {
    "agents": [
    {
    "id": "agent-0",
    "start_at": "wp-1",
    "capacity": {
    "weight_kg": 100
    },
    "cost": {}
    }
    ]
    }
  • Размер груза для каждой точки. Укажите тип точки (type) и размер груза (shipment_size).

    Например, забрать с точки 50 кг груза:

    {
    "waypoints": [
    {
    "id": "wp-0",
    "point": {
    "lat": 54.994814,
    "lon": 82.87837
    },
    "type": "pickup",
    "shipment_size": {
    "weight_kg": 50
    }
    }
    ]
    }

Избегание областей и типов дорог

При построении маршрута вы можете исключить определённые типы дорог, такие как грунтовые или платные, и указать области, которые будут избегаться. Избегание участков может повлиять на порядок и возможность посещения точек, а также на общую длину маршрута и время в пути. Максимальное количество исключаемых областей — 25.

Чтобы избегать дороги определённых типов, используйте параметр road_filters, например:

{
"options": {
"road_filters": ["toll_road"] // избегать платных дорог
}
}

Чтобы избегать область, задайте её координаты с помощью поля exclude, указав параметры:

  • points — координаты исключаемой области (массив точек):

    • x — градусы восточной долготы;
    • y — градусы северной широты.
  • type — форма исключаемой области:

    • point — круг с радиусом, равным extent (points — это центр окружности);
    • polyline — ломаная линия с шириной, равной extent (points — вершины линии);
    • polygon — многоугольник (points — вершины многоугольника).
  • extent — размер исключаемой области в метрах.

  • severity — как строго нужно избегать заданную область:

    • soft — избегать по возможности;
    • hard — избегать всегда.

Например, добавить строго избегаемую область в виде окружности в пример задачи:

{
"options": {
"exclude": [
{
"type": "point",
"severity": "hard",
"extent": 3000, // 3 км
"points": [
{
"x": 37.527,
"y": 55.720
}
]
}
]
}
}

Исключаемая область на карте

Даже если в результате избегания зоны количество точек в маршруте не изменится, может увеличиться длина маршрута или время в пути. Обратите внимание на параметры total_duration_s и total_distance_m в метриках результата.

Например, длина маршрута и время в пути из примера задачи без избегаемой области:

{
"total_duration_s": 3897, // 1 час
"total_distance_m": 55501 // 55.5 км
}

И с заданной выше избегаемой областью:

{
"total_duration_s": 7036, // 2 часа
"total_distance_m": 77815 // 78 км
}

Исключение точек и курьеров

Если задачу невозможно решить с соблюдением всех условий, TSP API предложит маршрут с исключением некоторых точек или курьеров. Информация об исключённых компонентах доступна в поле result ответа: массивы dropped_waypoints и dropped_agents.

Ответ содержит исключённые точки и курьеров с указанием причины. Например:

{
"result": {
"dropped_waypoints": [
{
"id": "wp-16",
"reason": "route_does_not_exist"
},
{
"id": "wp-18",
"reason": "route_does_not_exist"
},
{
"id": "wp-7",
"reason": "failed_time"
}
],
"dropped_agents": [
{
"id": "agent-1",
"reason": "empty_agent"
}
]
}
}

Причины исключения:

  • route_does_not_exist — точки, до которых невозможно построить маршрут;
  • failed_time — точки, которые курьер не успевает посетить;
  • failed_time_window_for_worktime — точки, у которых временное окно не совпадает с расписанием любого из курьеров;
  • empty_agent — курьеры, для которых отсутствуют маршруты (не определены точки, кроме заданной начальной или конечной).