otimização gratuita de rotas

Resolva rotas de entrega em segundos

Informe os pontos, escolha entre TSP, VRP ou matriz de distâncias e receba o resultado otimizado direto no navegador — com mapa, resumo e JSON para integrar. Sem cadastro.

TSP, VRP e matriz de distânciasSem cadastroResultado em JSON

Fluxo

Como funciona

Três passos e o resultado aparece no mapa e no JSON.

1

Informe os pontos

Digite lat/lng, importe um CSV/JSON ou busque por endereço.

2

Escolha e otimize

Selecione o tipo de problema (TSP, VRP ou matriz) e clique em Otimizar.

3

Visualize o resultado

Rota desenhada no mapa, resumo em números e JSON para baixar.

Problema

O que você quer resolver?

Cada tipo gera um payload diferente. Você só preenche os pontos.

Origem (depósito)

Paradas

3 pontos
NomeLatitudeLongitude
1
2
3

Mapa

4 pts

Carregando mapa…

Arraste os marcadores para ajustar. Para inserir pontos, ative "Adicionar ponto no mapa" e clique onde quiser.

Rota única (TSP)

Euclidiana (linha reta) · 3 pontos · origem definida

Integração

Usar via API

A mesma otimização disponível por HTTP. Jobs são assíncronos: envie, faça polling e receba o resultado.

Documentação interativa e testável

Explore e teste todos os endpoints (jobs, status, resultado e saúde) direto no Swagger UI.

1

Criar o job

POST /api/v1/jobs/{tipo} — retorna 202 com o id do job em PENDING.

2

Acompanhar o status

GET /api/v1/jobs/{id} — faça polling até DONE ou ERROR.

3

Receber o resultado

GET /api/v1/jobs/{id}/output — ou receba um POST no webhook.

Por tipo de problema

TSP — Rota única

Caixeiro viajante: visita todas as paradas partindo da origem, na ordem que minimiza o trajeto, e retorna ao início.

POST /api/v1/jobs/tsp

Corpo do request

Envelope { webhookUrl, input }. webhookUrl é opcional.

{
  "webhookUrl": "https://seu-servidor.com/hook",
  "input": {
    "matrixType": "EUCLIDIAN",
    "origin": { "lat": -23.5505, "lng": -46.6333 },
    "stops": [
      { "id": "p1", "name": "Parada 1", "location": { "lat": -23.5614, "lng": -46.6559 } },
      { "id": "p2", "name": "Parada 2", "location": { "lat": -23.5874, "lng": -46.6576 } },
      { "id": "p3", "name": "Parada 3", "location": { "lat": -23.5343, "lng": -46.6339 } }
    ]
  }
}

Resposta 202

202 Created — guarde o id para acompanhar.

{
  "id": "c8d3525c-ff82-4ec9-9c50-d4f753e85502",
  "type": "TSP",
  "status": "PENDING",
  "inputUrl": "http://localhost:8080/api/v1/jobs/.../input",
  "outputUrl": null,
  "statusUrl": "http://localhost:8080/api/v1/jobs/...",
  "createdAt": "2026-09-02T01:02:36Z",
  "startedAt": null,
  "finishedAt": null,
  "processingTimeMs": null
}

curl de exemplo

curl -X POST http://localhost:8080/api/v1/jobs/tsp \
  -H 'Content-Type: application/json' \
  -d '{
    "webhookUrl": "https://seu-servidor.com/hook",
    "input": {
      "matrixType": "EUCLIDIAN",
      "origin": { "lat": -23.5505, "lng": -46.6333 },
      "stops": [
        { "id": "p1", "name": "Parada 1", "location": { "lat": -23.5614, "lng": -46.6559 } },
        { "id": "p2", "name": "Parada 2", "location": { "lat": -23.5874, "lng": -46.6576 } },
        { "id": "p3", "name": "Parada 3", "location": { "lat": -23.5343, "lng": -46.6339 } }
      ]
    }
  }'

Campos

webhookUrl

URL que recebe um POST quando o job termina.

opcional
input.matrixType

"EUCLIDIAN" (linha reta) ou "STREET" (OSRM).

obrigatório
input.origin

{ lat, lng } do depósito (origem da rota).

obrigatório
input.stops[]

Paradas: id, name e location { lat, lng }. Mínimo 2.

obrigatório

Resultado: paradas otimizadas (optimized_stops), distância total em metros (distance_meters) e a rota (route_line).

VRP — Frota de veículos

Roteiriza a entrega distribuindo os clientes entre os veículos, respeitando o máximo de paradas, peso e volume de cada um.

POST /api/v1/jobs/vrp

Corpo do request

Envelope { webhookUrl, input } com clients e vehicles.

{
  "webhookUrl": "https://seu-servidor.com/hook",
  "input": {
    "matrixType": "EUCLIDIAN",
    "origin": { "lat": -23.5505, "lng": -46.6333 },
    "clients": [
      { "id": "c1", "name": "Cliente 1", "location": { "lat": -23.5614, "lng": -46.6559 }, "volumeLiters": 10, "weightKg": 120 },
      { "id": "c2", "name": "Cliente 2", "location": { "lat": -23.5874, "lng": -46.6576 }, "volumeLiters": 25, "weightKg": 340 }
    ],
    "vehicles": [
      { "name": "Van", "maxDeliveries": 10, "maxWeightKg": 1000, "maxVolumeLiters": 200 },
      { "name": "Carro", "maxDeliveries": 5, "maxWeightKg": 400, "maxVolumeLiters": 80 }
    ]
  }
}

Resposta 202

202 Created — o campo type vem como VRP.

{
  "id": "c8d3525c-ff82-4ec9-9c50-d4f753e85502",
  "type": "TSP",
  "status": "PENDING",
  "inputUrl": "http://localhost:8080/api/v1/jobs/.../input",
  "outputUrl": null,
  "statusUrl": "http://localhost:8080/api/v1/jobs/...",
  "createdAt": "2026-09-02T01:02:36Z",
  "startedAt": null,
  "finishedAt": null,
  "processingTimeMs": null
}

curl de exemplo

curl -X POST http://localhost:8080/api/v1/jobs/vrp \
  -H 'Content-Type: application/json' \
  -d '{
    "webhookUrl": "https://seu-servidor.com/hook",
    "input": {
      "matrixType": "EUCLIDIAN",
      "origin": { "lat": -23.5505, "lng": -46.6333 },
      "clients": [
        { "id": "c1", "name": "Cliente 1", "location": { "lat": -23.5614, "lng": -46.6559 }, "volumeLiters": 10, "weightKg": 120 },
        { "id": "c2", "name": "Cliente 2", "location": { "lat": -23.5874, "lng": -46.6576 }, "volumeLiters": 25, "weightKg": 340 }
      ],
      "vehicles": [
        { "name": "Van", "maxDeliveries": 10, "maxWeightKg": 1000, "maxVolumeLiters": 200 },
        { "name": "Carro", "maxDeliveries": 5, "maxWeightKg": 400, "maxVolumeLiters": 80 }
      ]
    }
  }'

Campos

webhookUrl

URL que recebe um POST quando o job termina.

opcional
input.matrixType

"EUCLIDIAN" (linha reta) ou "STREET" (OSRM).

obrigatório
input.origin

{ lat, lng } do depósito (saída das rotas).

obrigatório
input.clients[]

Clientes: id, name, location { lat, lng }, volumeLiters (L) e weightKg (kg). Mínimo 1.

obrigatório
input.vehicles[]

Veículos: name, maxDeliveries, maxWeightKg e maxVolumeLiters. Mínimo 1.

obrigatório

Resultado: uma rota por veículo (routes), com clientes, distância, peso e volume de cada rota.

Matriz de distâncias

Calcula as distâncias entre todos os pares de pontos informados — não usa origem: a matriz cobre todos os pares.

POST /api/v1/jobs/distance-matrix

Corpo do request

Envelope { webhookUrl, input } com as coordenadas.

{
  "webhookUrl": "https://seu-servidor.com/hook",
  "input": {
    "matrixType": "EUCLIDIAN",
    "coordinates": [
      { "lat": -23.5614, "lng": -46.6559 },
      { "lat": -23.5874, "lng": -46.6576 },
      { "lat": -23.5343, "lng": -46.6339 }
    ]
  }
}

Resposta 202

202 Created — o campo type vem como DISTANCE_MATRIX.

{
  "id": "c8d3525c-ff82-4ec9-9c50-d4f753e85502",
  "type": "TSP",
  "status": "PENDING",
  "inputUrl": "http://localhost:8080/api/v1/jobs/.../input",
  "outputUrl": null,
  "statusUrl": "http://localhost:8080/api/v1/jobs/...",
  "createdAt": "2026-09-02T01:02:36Z",
  "startedAt": null,
  "finishedAt": null,
  "processingTimeMs": null
}

curl de exemplo

curl -X POST http://localhost:8080/api/v1/jobs/distance-matrix \
  -H 'Content-Type: application/json' \
  -d '{
    "webhookUrl": "https://seu-servidor.com/hook",
    "input": {
      "matrixType": "EUCLIDIAN",
      "coordinates": [
        { "lat": -23.5614, "lng": -46.6559 },
        { "lat": -23.5874, "lng": -46.6576 },
        { "lat": -23.5343, "lng": -46.6339 }
      ]
    }
  }'

Campos

webhookUrl

URL que recebe um POST quando o job termina.

opcional
input.matrixType

"EUCLIDIAN" (linha reta) ou "STREET" (OSRM).

obrigatório
input.coordinates[]

Pontos { lat, lng } — a matriz é entre todos os pares. Mínimo 2.

obrigatório

Resultado: matriz N×N de distâncias em metros (matrix) mais as coordenadas.

Acompanhar o job e receber o resultado

Faça polling no status até DONE (ou ERROR) e depois baixe o resultado. Todos os campos da entidade job vêm no status.

GET /api/v1/jobs/{id}
Na filaPENDINGProcessandoRUNNINGConcluídoDONEErroERROR

Resposta 200 (status)

status: PENDING → RUNNING → DONE | ERROR.

{
  "id": "2603bbcc-5142-4e09-8cd4-0c96453e8056",
  "type": "TSP",
  "status": "DONE",
  "inputUrl": "http://localhost:8080/api/v1/jobs/.../input",
  "outputUrl": "http://localhost:8080/api/v1/jobs/.../output",
  "statusUrl": "http://localhost:8080/api/v1/jobs/...",
  "webhookUrl": null,
  "errorMessage": null,
  "processingTimeMs": 2,
  "createdAt": "2026-09-02T01:02:36Z",
  "startedAt": null,
  "finishedAt": "2026-09-02T01:02:36Z",
  "inputPath": "inputs/....json",
  "outputPath": "solutions/....json"
}

Resultado — GET /api/v1/jobs/{id}/output

Disponível quando o status é DONE (exemplo TSP).

{
  "optimized_stops": [
    {
      "id": "p1",
      "customer_name": "Parada 1",
      "address": { "latitude": -23.5614, "longitude": -46.6559 }
    }
  ],
  "route_line": [
    { "lat": -23.5505, "lng": -46.6333 },
    { "lat": -23.5614, "lng": -46.6559 }
  ],
  "distance_meters": 33595.49,
  "time_to_solve_ms": 0.23
}

Webhook opcional

Se webhookUrl for enviado no POST, o backend chama essa URL com um POST quando o job termina — não precisa de polling.

Rate limit por IP

~10 jobs/min, ~100 consultas/min e ~30 geocodificações/min. Em excesso, a API responde 429.