API de Rutas para Transporte: Guía para Desarrolladores Python

API de Rutas para Transporte: Guía para Desarrolladores Python

Introducción

La integración de APIs de optimización de rutas en aplicaciones de transporte se ha convertido en un diferenciador competitivo. Esta guía técnica muestra cómo implementar una API de rutas en Python para optimizar operaciones logísticas.

> Nota: Esta guía está orientada a desarrolladores que necesitan integrar servicios de rutas en sus aplicaciones.

---

Fundamentos de APIs de Rutas

Conceptos Básicos

Una API de rutas para transporte permite:

- Cálculo de rutas óptimas considerando múltiples factores - Optimización de trayectos con restricciones específicas - Estimación de tiempos y costes de combustible - Predicción de tráfico basada en datos históricos

Componentes de una Solicitud

```python import requests import json

def calcular_ruta(origen, destino, parametros): """ Calcula ruta óptima entre dos puntos """ url = "https://api.cargoffer.com/v1/rutas"

payload = { "origen": { "latitud": origen["lat"], "longitud": origen["lon"], "direccion": origen["direccion"] }, "destino": { "latitud": destino["lat"], "longitud": destino["lon"], "direccion": destino["direccion"] }, "vehiculo": { "tipo": "camion", "peso_kg": parametros.get("peso", 20000), "altura_m": parametros.get("altura", 4.5), "consumo_100km": parametros.get("consumo", 35) }, "preferencias": { "evitar_peajes": parametros.get("evitar_peajes", False), "evitar_carreteras_lentas": parametros.get("evitar_carreteras", False), "prioridad": parametros.get("prioridad", "tiempo") # tiempo | distancia | coste } }

headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" }

response = requests.post(url, json=payload, headers=headers) return response.json() ```

---

Autenticación

Obtener API Key

```python

Guardar credenciales de forma segura

import os

API_KEY = os.environ.get("CARGOFFER_API_KEY") API_SECRET = os.environ.get("CARGOFFER_API_SECRET") ```

Autenticación JWT

```python import jwt import time

def crear_token_jwt(): """ Genera token JWT para autenticación """ now = int(time.time())

payload = { "iat": now, "exp": now + 3600, # 1 hora "aud": "/admin/" }

header = { "alg": "HS256", "typ": "JWT", "kid": API_KEY.split(":")[0] }

secret = API_KEY.split(":")[1] token = jwt.encode(payload, secret, algorithm="HS256", headers=header)

return token ```

---

Endpoints Principales

1. Calcular Ruta Simple

```python def ruta_simple(origen, destino): """Calcula ruta básica entre dos puntos"""

response = requests.get( f"{BASE_URL}/rutas", params={ "origen": f"{origen['lat']},{origen['lon']}", "destino": f"{destino['lat']},{destino['lon']}", "vehiculo": "camion" }, headers={"Authorization": f"Bearer {token}"} )

return response.json() ```

2. Optimizar Múltiples Paradas

```python def optimizar_multiples_paradas(paradas, optimizar_orden=True): """ Optimiza ruta con múltiples paradas El parámetro optimizar_orden determina si la API calcula el orden óptimo """

payload = { "paradas": [ {"lat": p["lat"], "lon": p["lon"], "tipo": p.get("tipo", "entrega")} for p in paradas ], "configuracion": { "optimizar_orden": optimizar_orden, "vehiculo": {"tipo": "camion_articulado"}, "restricciones": { "tiempo_maximo_ruta": 480, # minutos "paradas_maximas": 15 } } }

response = requests.post( f"{BASE_URL}/rutas/optimizar", json=payload, headers={"Authorization": f"Bearer {token}"} )

return response.json() ```

3. Calcular Costes

```python def calcular_coste_ruta(ruta_id, precio_gasolina=1.65, precio_diesel=1.45): """ Calcula coste estimado de una ruta existente """

payload = { "ruta_id": ruta_id, "costes": { "combustible": { "tipo": "diesel", "precio_por_litro": precio_diesel, "consumo_real": True # Considera peso y terrain }, "peajes": True, "tiempo_conductor": 15.50, # €/hora "amortizacion_km": 0.12 # €/km } }

response = requests.post( f"{BASE_URL}/rutas/{ruta_id}/costes", json=payload, headers={"Authorization": f"Bearer {token}"} )

return response.json() ```

4. Predicción de Tráfico

```python def predecir_trafico(ruta_id, fecha_hora): """ Predice condiciones de tráfico para una ruta y hora específicas Útil para planificación de tiempos de llegada """

params = { "ruta_id": ruta_id, "fecha_hora": fecha_hora.isoformat(), # datetime "incluir_alternativas": True }

response = requests.get( f"{BASE_URL}/trafico/prediccion", params=params, headers={"Authorization": f"Bearer {token}"} )

return response.json() ```

---

Ejemplo Completo: Optimizador de Rutas

```python import requests from datetime import datetime, timedelta import json

class OptimizadorRutas: """ Cliente completo para optimización de rutas de transporte """

def __init__(self, api_key, base_url="https://api.cargoffer.com/v1"): self.api_key = api_key self.base_url = base_url self.headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }

def optimizar_entregas(self, entregas, restricciones=None): """ Optimiza ruta para múltiples entregas

Args: entregas: List[dict] con claves 'lat', 'lon', 'ventana_horaria' restricciones: dict con restricciones opcionales """

payload = { "paradas": [ { "lat": e["lat"], "lon": e["lon"], "ventana_inicio": e.get("ventana_inicio"), "ventana_fin": e.get("ventana_fin"), "duracion_minutos": e.get("duracion", 30) } for e in entregas ], "vehiculo": { "tipo": "camion", "capacidad_kg": restricciones.get("capacidad", 20000), "altura_m": restricciones.get("altura", 4.2) }, "optimizar": { "objetivo": restricciones.get("objetivo", "coste"), # tiempo | distancia | coste "evitar": restricciones.get("evitar", []) } }

response = requests.post( f"{self.base_url}/rutas/optimizar", json=payload, headers=self.headers )

if response.status_code == 200: return response.json() else: raise Exception(f"Error: {response.text}")

def obtener_ruta(self, ruta_id): """Obtiene detalles de una ruta"""

response = requests.get( f"{self.base_url}/rutas/{ruta_id}", headers=self.headers ) return response.json()

def estimar_coste(self, ruta_id, parametros_coste): """ Estima coste detallado de una ruta """

response = requests.post( f"{self.base_url}/rutas/{ruta_id}/coste", json=parametros_coste, headers=self.headers ) return response.json()

Uso ejemplo

if __name__ == "__main__":

# Inicializar cliente cliente = OptimizadorRutas(API_KEY)

# Definir entregas entregas = [ {"lat": 40.4168, "lon": -3.7038, "ventana_inicio": "09:00", "ventana_fin": "11:00", "duracion": 30}, {"lat": 41.3851, "lon": 2.1734, "ventana_inicio": "14:00", "ventana_fin": "17:00", "duracion": 45}, {"lat": 39.4699, "lon": -0.3763, "ventana_inicio": "09:00", "ventana_fin": "11:00", "duracion": 30}, ]

# Optimizar resultado = cliente.optimizar_entregas(entregas, {"objetivo": "coste"})

print(f"Ruta óptima: {resultado['ruta']['distancia_km']} km") print(f"Tiempo total: {resultado['ruta']['tiempo_minutos']} min") print(f"Coste estimado: {resultado['coste']['total']}€") ```

---

Mejores Prácticas

Manejo de Errores

```python import logging from requests.exceptions import RequestException

class RutaAPIError(Exception): pass

def safe_request(func): """Decorador para manejo de errores""" def wrapper(args, kwargs): try: return func(args, kwargs) except RequestException as e: logging.error(f"Error de conexión: {e}") raise RutaAPIError("Problema de conexión con API de rutas") except Exception as e: logging.error(f"Error inesperado: {e}") raise return wrapper ```

Retry Logic

```python from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry

session = requests.Session() retry = Retry( total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry) session.mount('https://', adapter) ```

Rate Limiting

```python import time from collections import deque

class RateLimiter: """Limita peticiones a la API"""

def __init__(self, max_peticiones=100, ventana_segundos=60): self.max = max_peticiones self.ventana = ventana_segundos self.cola = deque()

def wait(self): ahora = time.time() # Limpiar peticiones antiguas while self.cola and ahora - self.cola[0] > self.ventana: self.cola.popleft()

# Esperar si llegamos al límite if len(self.cola) >= self.max: tiempo_espera = self.ventana - (ahora - self.cola[0]) time.sleep(tiempo_espera)

self.cola.append(ahora) ```

---

FAQ: Preguntas Técnicas

¿Qué formato de coordenadas acepta la API?

Aceptamos tanto latitud/longitud como direcciones. La API geocodifica automáticamente.

```python

Con coordenadas

{"lat": 40.4168, "lon": -3.7038}

O con dirección

{"direccion": "Calle Gran Vía 1, Madrid, España"} ```

¿Puedo usar la API offline?

No, requiere conectividad. Para modo offline, contacta soporte para opciones enterprise.

¿Cómo calculamos el consumo de combustible?

Usamos algoritmos que consideran peso del vehículo, tipo de ruta, pendiente y condiciones de tráfico reales.

---

Conclusión

La integración de APIs de rutas en Python permite optimizar operaciones logísticas significativamente. Los ejemplos mostrados cubren los casos de uso principales.

Pasos siguientes:

1. Solicitar API key de desarrollo 2. Probar endpoints en sandbox 3. Implementar en producción con rate limiting 4. Monitorizar métricas de uso

---

Documentación completa →

Probar sandbox →**