Resolva o problema de roteamento com múltiplos veículos e janelas de horário (VRPTW) em segundos. Use nossa API REST ou portal web — sem instalação, 100% em nuvem.
Funcionalidades
Nosso engine resolve restrições que soluções convencionais ignoram.
Cada entrega pode ter horário específico (ex: 9h–12h). O solver respeita essas restrições ou explica por que não foi possível atender.
Velocidade varia por hora do dia. São Paulo: até 2.5× mais lento nos picos (7–9h e 17–19h). Rio de Janeiro: 2.0×. Outras cidades: 1.5–1.8×.
CSV com sequência, JSON completo, KML para Google Maps, mapa HTML interativo (Folium) e relatório TXT legível — tudo em um único ZIP.
Cada entrega não atendida tem um motivo claro: "Capacidade insuficiente", "Janela incompatível" ou "Veículos indisponíveis". Sem caixa-preta.
O traçado segue o caminho real pelas ruas — não linha reta. Seu KML no Google Maps mostra a rota exatamente como o motorista vai percorrer.
Upload dos CSVs → otimização completa com VRPTW + TDVRP → download do ZIP. Tudo em menos de dois minutos para qualquer operação do dia.
Casos de Uso
O EasyRouter adapta-se a qualquer modelo de distribuição com múltiplos pontos e restrições de horário.
50 a 200+ pedidos/dia com janelas de entrega agendadas pelos clientes.
Recolhimento de embalagens, devoluções e resíduos com rotas eficientes.
Representantes comerciais com carteira de clientes e compromissos fixos de horário.
Técnicos de campo com agendamentos, tempo de serviço variável e SLA a cumprir.
Passo a Passo
Do arquivo CSV ao resultado otimizado em menos de 2 minutos. Integre via API REST em qualquer linguagem ou use nosso portal web sem escrever uma linha de código.
Testar agoraEndereço, janela de horário (ex: 09:00–12:00), peso, volume e prioridade para cada ponto. Um CSV de veículos define capacidade e jornada.
POST para /v1/roteirizar com sua API key — ou arraste o CSV no portal web. Receba o job_id em milissegundos.
VRPTW com TDVRP: distâncias reais, trânsito por horário, capacidade, almoço, pausa obrigatória. Refinamento iterativo até a melhor solução.
CSV com sequência, JSON completo, KML para Google Maps, mapa HTML interativo e relatório TXT por veículo — tudo compactado.
Polling com GET /v1/job/{id} para monitorar status. Quando concluído, faça o download automático e alimente seu TMS ou WMS.
Formatos de Saída
Um ZIP com tudo que você precisa — do mapa visual ao JSON estruturado para integração.
# rotas.csv — sequência de paradas por veículo veiculo_id,ordem,entrega_id,endereco,chegada,saida,distancia_km V001,1,E012,Av. Paulista 1578, São Paulo,09:14,09:24,3.2 V001,2,E007,Rua Augusta 850, São Paulo,09:41,09:51,1.8 V002,1,E003,Al. Santos 211, São Paulo,08:55,09:05,2.1
{
"job_id": "3c930d3e-dedb-47a4-a8ac-7928faffa180",
"status": "concluido",
"n_entregas_atendidas": 42,
"n_entregas_nao_atendidas": 3,
"tempo_solver_s": 61.4,
"rotas": [
{
"veiculo": "V001",
"n_paradas": 14,
"distancia_total_km": 38.7,
"tempo_total_min": 312,
"paradas": [...]
}
],
"nao_atendidas": [
{ "id": "E015", "motivo": "Janela de tempo incompatível" }
]
}
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2"> <Document> <name>EasyRouter — Rotas do Dia</name> <Placemark> <name>V001 — Rota completa</name> <LineString> <coordinates> -46.6333,-23.5505 -46.6540,-23.5617 ... </coordinates> </LineString> </Placemark> </Document> </kml>
═══════════════════════════════════════════════ EASYROUTER — RELATÓRIO DE ROTAS ═══════════════════════════════════════════════ VEÍCULO: V001 Saída do depósito: 07:00 Retorno ao depósito: 16:48 Distância total: 38.7 km Entregas realizadas: 14 / 14 01. E012 — Av. Paulista 1578 ............... 09:14 02. E007 — Rua Augusta 850 ................. 09:41 03. E023 — Al. Campinas 600 ................ 10:08 [ALMOÇO] 12:00 – 13:00 04. E031 — R. da Consolação 1400 ........... 13:22
# POST /v1/roteirizar curl -X POST https://api.easyrouter.io/v1/roteirizar \ -H "Authorization: Bearer rtzdlv_sua_chave" \ -F "entregas=@entregas.csv" \ -F "veiculos=@veiculos.csv" # Resposta 202 Accepted { "success": true, "data": { "job_id": "3c930d3e-dedb-47a4", "status": "pendente", "n_entregas": 45, "n_veiculos": 3 } } # GET /v1/job/{id}/download → ZIP com todos os resultados
Integração
API REST padrão com autenticação Bearer token — integre em minutos com qualquer stack tecnológico. Ou use o portal web sem escrever código.
# 1. Enviar job de roteirização curl -X POST https://www.qtec.net.br/EasyRouter/v1/roteirizar \ -H "Authorization: Bearer rtzdlv_sua_chave_aqui" \ -F "entregas=@entregas.csv" \ -F "veiculos=@veiculos.csv" # Resposta 202: { "success": true, "data": { "job_id": "3c930d3e...", "status": "pendente" } } # 2. Consultar status do job curl -H "Authorization: Bearer rtzdlv_sua_chave_aqui" \ https://www.qtec.net.br/EasyRouter/v1/job/3c930d3e... # 3. Baixar resultado (quando status = "concluido") curl -H "Authorization: Bearer rtzdlv_sua_chave_aqui" \ -o resultado.zip \ https://www.qtec.net.br/EasyRouter/v1/job/3c930d3e.../download
// PHP — enviar job e fazer polling $apiKey = 'rtzdlv_sua_chave_aqui'; $base = 'https://www.qtec.net.br/EasyRouter/v1'; // 1. Enviar $ch = curl_init("$base/roteirizar"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $apiKey"], CURLOPT_POSTFIELDS => [ 'entregas' => new CURLFile('entregas.csv'), 'veiculos' => new CURLFile('veiculos.csv'), ], ]); $jobId = json_decode(curl_exec($ch), true)['data']['job_id']; curl_close($ch); // 2. Polling a cada 10s do { sleep(10); $ch2 = curl_init("$base/job/$jobId"); curl_setopt_array($ch2, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $apiKey"]]); $status = json_decode(curl_exec($ch2), true)['data']['status']; } while (!in_array($status, ['concluido', 'erro'])); // 3. Download do ZIP $ch3 = curl_init("$base/job/$jobId/download"); curl_setopt_array($ch3, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $apiKey"]]); file_put_contents('resultado.zip', curl_exec($ch3));
import requests, time API_KEY = "rtzdlv_sua_chave_aqui" BASE = "https://www.qtec.net.br/EasyRouter/v1" HEADERS = {"Authorization": f"Bearer {API_KEY}"} # 1. Enviar job resp = requests.post( f"{BASE}/roteirizar", headers=HEADERS, files={ "entregas": open("entregas.csv", "rb"), "veiculos": open("veiculos.csv", "rb"), } ) job_id = resp.json()["data"]["job_id"] print(f"Job criado: {job_id}") # 2. Polling até conclusão while True: time.sleep(10) data = requests.get(f"{BASE}/job/{job_id}", headers=HEADERS).json()["data"] print(f"Status: {data['status']}") if data["status"] in ("concluido", "erro"): break # 3. Baixar ZIP zip_bytes = requests.get(f"{BASE}/job/{job_id}/download", headers=HEADERS).content with open("resultado.zip", "wb") as f: f.write(zip_bytes) print("✓ resultado.zip salvo")
// Node.js — usando node-fetch e form-data // npm install node-fetch form-data const FormData = require('form-data'); const fetch = require('node-fetch'); const fs = require('fs'); const API_KEY = 'rtzdlv_sua_chave_aqui'; const BASE = 'https://www.qtec.net.br/EasyRouter/v1'; const auth = { Authorization: `Bearer ${API_KEY}` }; (async () => { // 1. Enviar const form = new FormData(); form.append('entregas', fs.createReadStream('entregas.csv')); form.append('veiculos', fs.createReadStream('veiculos.csv')); const { data } = await fetch(`${BASE}/roteirizar`, { method: 'POST', headers: { ...auth, ...form.getHeaders() }, body: form }).then(r => r.json()); let status = ''; // 2. Polling while (!['concluido', 'erro'].includes(status)) { await new Promise(r => setTimeout(r, 10000)); status = (await fetch(`${BASE}/job/${data.job_id}`, { headers: auth }).then(r => r.json())).data.status; console.log(`Status: ${status}`); } // 3. Download const buf = await fetch(`${BASE}/job/${data.job_id}/download`, { headers: auth }).then(r => r.buffer()); fs.writeFileSync('resultado.zip', buf); console.log('✓ resultado.zip salvo'); })();
// Java — OkHttp 4.x (Maven: com.squareup.okhttp3:okhttp:4.12.0) import okhttp3.*; import org.json.JSONObject; import java.io.*; import java.nio.file.*; OkHttpClient client = new OkHttpClient(); String API_KEY = "rtzdlv_sua_chave_aqui"; String BASE = "https://www.qtec.net.br/EasyRouter/v1"; // 1. Enviar job RequestBody multipart = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("entregas", "entregas.csv", RequestBody.create(new File("entregas.csv"), MediaType.parse("text/csv"))) .addFormDataPart("veiculos", "veiculos.csv", RequestBody.create(new File("veiculos.csv"), MediaType.parse("text/csv"))) .build(); Request post = new Request.Builder() .url(BASE + "/roteirizar") .header("Authorization", "Bearer " + API_KEY) .post(multipart).build(); String jobId = new JSONObject(client.newCall(post).execute().body().string()) .getJSONObject("data").getString("job_id"); // 2. Polling String status = ""; while (!status.equals("concluido") && !status.equals("erro")) { Thread.sleep(10000); Request get = new Request.Builder().url(BASE + "/job/" + jobId) .header("Authorization", "Bearer " + API_KEY).build(); status = new JSONObject(client.newCall(get).execute().body().string()) .getJSONObject("data").getString("status"); } // 3. Download ZIP Request dl = new Request.Builder().url(BASE + "/job/" + jobId + "/download") .header("Authorization", "Bearer " + API_KEY).build(); Files.write(Paths.get("resultado.zip"), client.newCall(dl).execute().body().bytes());
Prefere não programar? Use o portal web — arraste o CSV e baixe os resultados pelo browser, sem escrever uma linha de código.
Por que EasyRouter?
Concorrentes usam tempo de percurso constante. Nós variamos a velocidade por faixa horária — o resultado é um horário de chegada real.
O KML segue o traçado real das ruas — não uma linha reta entre dois pontos. Abra no Google Maps e veja exatamente o caminho do motorista.
Cada entrega não realizada tem um motivo explicado. Você sabe exatamente o que ajustar para o próximo planejamento.
Integre em qualquer linguagem: Python, JavaScript, PHP, Java, .NET. Autenticação por Bearer token, respostas JSON, sem SDK proprietário.
Não é desenvolvedor? Use o portal web: arraste o CSV, aguarde o processamento e baixe o ZIP. Tudo via browser, sem instalar nada.
Prioridade 1 (urgente) é quase obrigatória. Prioridade 3 é descartada primeiro quando a agenda está cheia. Você controla o que é crítico.
Perguntas Frequentes