API Routing

Itinéraires, matrices & isochrones

Valhalla sous le capot. ETA ajustés au trafic via modèle ML, instructions turn-by-turn enrichies avec les landmarks locaux. Polylines encodées en précision 6 (facteur 10⁻⁶, pas 10⁻⁵ comme Google).

Comment ça marche

  Votre app                AfriMap Gateway              Valhalla
     │                          │                          │
     │  POST /v1/route          │                          │
     │ ─────────────────────►   │                          │
     │                          │  POST /route             │
     │                          │ ─────────────────────►   │
     │                          │                          │
     │                          │  ◄── polyline + maneuvers│
     │                          │                          │
     │                          │  enrichit landmarks      │
     │                          │  (PostGIS 200m radius)   │
     │                          │                          │
     │                          │  ajuste ETA              │
     │                          │  (TimescaleDB + ML)      │
     │                          │                          │
     │  ◄── réponse enrichie    │                          │
     │                          │                          │

Le gateway reçoit votre requête, la transmet à Valhalla pour le calcul d'itinéraire, puis enrichit la réponse avec les landmarks PostGIS proches de chaque point de virage et ajuste la durée via le modèle ML trafic.

Calculer un itinéraire simple

TypeScriptJavaScript
const { routes } = await client.routing.route({ origin: { lat: 5.3197, lng: -4.0167 }, // Plateau destination: { lat: 5.3480, lng: -3.9904 }, // Cocody mode: 'auto', language: 'fr', })
TerminalcURL
 curl -X POST https://api.afrimap.ci/v1/route \ -H "X-AfriMap-Key: afm_test_..." \ -H "Content-Type: application/json" \ -d '{ "origin": { "lat": 5.3197, "lng": -4.0167 }, "destination": { "lat": 5.3480, "lng": -3.9904 }, "mode": "auto", "language": "fr" }'

Réponse

JSONRéponse route
 { "routes": [ { "distance": 4200, "duration": 780, "duration_enhanced": 660, "geometry": "s~bnFdnabO...", "summary": "Boulevard de la République, Pont Général de Gaulle", "legs": [ { "distance": 4200, "duration": 780, "maneuvers": [ { "type": "depart", "instruction": "Dirigez-vous vers le nord sur Avenue Marchand", "distance": 300, "duration": 45, "begin_shape_index": 0, "end_shape_index": 12, "street_names": ["Avenue Marchand"], "verbal_pre_transition_instruction": "Dirigez-vous vers le nord sur Avenue Marchand pendant 300 metres", "landmark_nearby": { "name": "Cathédrale Saint-Paul", "distance_m": 85, "bearing": "left" } } ] } ] } ] }

Champs clés

  • distance — distance en mètres
  • duration — durée brute Valhalla (secondes)
  • duration_enhanced — durée ajustée trafic ML
  • geometry — polyline encodée précision 6
  • maneuvers[] — instructions pas-à-pas

Modes de transport

  • auto — voiture (défaut)
  • bicycle — vélo
  • pedestrian — piéton
  • motorcycle — moto (costing custom Abidjan)

Décoder la polyline

Attention : Valhalla encode les polylines en précision 6 (facteur 10⁻⁶). Google Maps utilise la précision 5 (10⁻⁵). Si vous réutilisez un décodeur Google, vos coordonnées seront décalées de 10x. Tous les SDKs AfriMap intègrent le bon décodeur.
TypeScriptDécodeur précision 6
function decodePolyline(encoded: string): [number, number][] { const coords: [number, number][] = [] let index = 0, lat = 0, lng = 0while (index < encoded.length) { for (const target of ['lat', 'lng']) { let shift = 0, result = 0, byte: number do { byte = encoded.charCodeAt(index++) - 63 result |= (byte & 0x1f) << shift shift += 5 } while (byte >= 0x20) const delta = result & 1 ? ~(result >> 1) : result >> 1if (target === 'lat') lat += delta else lng += delta } coords.push([lat / 1e6, lng / 1e6]) // 1e6 = precision 6! } return coords }

Routes alternatives

Demandez jusqu'à 3 alternatives pour laisser l'utilisateur choisir :

TypeScriptAvec alternatives
const { routes } = await client.routing.route({ origin: { lat: 5.3197, lng: -4.0167 }, destination: { lat: 5.3364, lng: -4.0694 }, // Yopougon mode: 'auto', alternatives: 2, // jusqu'a 2 alternatives }) // routes[0] = meilleur itinéraire// routes[1], routes[2] = alternatives (si dispo)

Matrice de distances

Calcule les temps de trajet entre N origines et M destinations en un seul appel. Indispensable pour le dispatch VTC (trouver le chauffeur le plus proche).

TypeScriptMatrice N×M
const matrix = await client.routing.matrix({ origins: [ { lat: 5.32, lng: -4.02 }, // chauffeur 1 { lat: 5.34, lng: -3.99 }, // chauffeur 2 { lat: 5.35, lng: -4.01 }, // chauffeur 3 ], destinations: [ { lat: 5.31, lng: -4.00 }, // passager ], mode: 'auto', }) // matrix.durations = [[420], [180], [300]] → chauffeur 2 est le plus proche// matrix.distances = [[3200], [1400], [2100]]

Isochrones

Génère un polygone représentant la zone atteignable depuis un point donné dans un temps ou une distance donnée. Utile pour les zones de couverture de livraison.

TypeScriptIsochrone 15 minutes
const iso = await client.routing.isochrone({ location: { lat: 5.3197, lng: -4.0167 }, time: 900, // 15 min en secondes mode: 'auto', }) // iso.geometry = GeoJSON Polygon// Affichez-le sur la carte avec map.addGeoJSON(iso.geometry)

Map Matching (snap GPS)

Prend une trace GPS bruitée et la « snappe » sur le réseau routier. Essentiel pour nettoyer les traces chauffeurs avant de calculer des vitesses par segment.

TypeScriptMap matching
const matched = await client.routing.match({ shape: [ { lat: 5.3190, lng: -4.0170, time: 1713300000 }, { lat: 5.3195, lng: -4.0165, time: 1713300005 }, { lat: 5.3202, lng: -4.0158, time: 1713300010 }, // ... points GPS bruts ], mode: 'auto', }) // matched.geometry = trace snappée sur routes// matched.edges = segments routiers traversés avec vitesses

Optimisation multi-stops (TSP)

Réordonne une liste de stops pour minimiser le temps de trajet total. Le « problème du voyageur de commerce » appliqué à la livraison.

TypeScriptOptimisation de tournée
const optimized = await client.routing.optimize({ locations: [ { lat: 5.3197, lng: -4.0167 }, // départ (entrepôt) { lat: 5.3480, lng: -3.9904 }, // livraison A { lat: 5.3364, lng: -4.0694 }, // livraison B { lat: 5.4194, lng: -4.0200 }, // livraison C ], mode: 'auto', }) // optimized.waypoint_order = [0, 2, 1, 3] → ordre optimal

Options avancées

ParamètreTypeDéfautDescription
modestring"auto"auto, bicycle, pedestrian, motorcycle
languagestring"fr"Langue des instructions (fr, en)
alternativesinteger0Nombre de routes alternatives (0-3)
avoid_tollsbooleanfalseEviter les routes à péage
avoid_unpavedbooleanfalseEviter les routes non goudronnées
directions_typestring"maneuvers"none (pas d'instructions) ou maneuvers
waypointsLatLng[][]Étapes intermédiaires

Endpoints

GET/v1/route

Compute an itinerary (GET, query string)

Same semantics as POST /v1/route but with origin/destination passed as `lat,lng` pairs on the query string. Convenient for quick sanity checks from cURL; prefer POST for multi-stop or typed payloads.

Paramètres

NomEmplacementTypeDescription
origin requiredquerystring`lat,lng` pair.
destination requiredquerystring`lat,lng` pair.
mode queryTravelMode
language querystring

Réponses

  • 200Route computed.

    object

Exemples de code

curl "https://api.afrimap.ci/v1/route?origin=5.3197,-4.0167&destination=5.3480,-3.9904&mode=auto&language=fr" \
  -H "X-AfriMap-Key: $AFM_KEY"

Testez-le

Essayer en direct

GET /v1/route

Collez une clé sandbox afm_test_…. La requête part directement de votre navigateur vers le gateway, aucun proxy côté portail.

`lat,lng` pair.

`lat,lng` pair.

GET http://localhost:8090/v1/route?origin=5.3197%2C-4.0167&destination=5.3480%2C-3.9904&language=fr
POST/v1/route

Compute an itinerary (POST, JSON body)

Returns one or more itineraries between two (or more) points with a precision-6 encoded polyline, three verbal instruction variants per maneuver (pre/alert/post), and — when traffic data is available — an ML-enhanced ETA alongside the raw Valhalla duration.

Corps de la requête

Schéma : RouteRequest

JSONExemple
{
  "origin": {
    "lat": 5.3197,
    "lng": -4.0167
  },
  "destination": {
    "lat": 5.348,
    "lng": -3.9904
  },
  "mode": "auto",
  "language": "fr"
}

Réponses

  • 200Route(s) computed.

    object

  • 400Validation error.

    Error

  • 401Missing or invalid API key.
  • 429Rate limit exceeded.

Exemples de code

curl -X POST https://api.afrimap.ci/v1/route \
  -H "X-AfriMap-Key: $AFM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "origin":      { "lat": 5.3197, "lng": -4.0167 },
    "destination": { "lat": 5.3480, "lng": -3.9904 },
    "mode":        "auto",
    "language":    "fr"
  }'

Testez-le

Essayer en direct

POST /v1/route

Collez une clé sandbox afm_test_…. La requête part directement de votre navigateur vers le gateway, aucun proxy côté portail.

POST http://localhost:8090/v1/route
POST/v1/matrix

Distance / duration matrix

Computes a distance + duration matrix for up to 500 origin/destination pairs per call. Typical use: dispatching the nearest available driver across a fleet.

Corps de la requête

Schéma : MatrixRequest

JSONExemple
{
  "origins": [
    {
      "lat": 5.3197,
      "lng": -4.0167
    }
  ],
  "destinations": [
    {
      "lat": 5.348,
      "lng": -3.9904
    },
    {
      "lat": 5.3364,
      "lng": -4.0694
    }
  ],
  "mode": "auto"
}

Réponses

  • 200Matrix.

    object

Exemples de code

curl -X POST https://api.afrimap.ci/v1/matrix \
  -H "X-AfriMap-Key: $AFM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "origins":      [{"lat":5.3197,"lng":-4.0167}],
    "destinations":[{"lat":5.3480,"lng":-3.9904},{"lat":5.3364,"lng":-4.0694}],
    "mode": "auto"
  }'

Testez-le

Essayer en direct

POST /v1/matrix

Collez une clé sandbox afm_test_…. La requête part directement de votre navigateur vers le gateway, aucun proxy côté portail.

POST http://localhost:8090/v1/matrix
GET/v1/isochrone

Reachability polygon

Returns a GeoJSON polygon of the area reachable within N minutes from a point. Supports driving, walking, and cycling costing profiles.

Paramètres

NomEmplacementTypeDescription
lat requiredquerynumber
lng requiredquerynumber
time requiredqueryintegerMinutes.
mode queryTravelMode

Réponses

  • 200GeoJSON FeatureCollection with one Polygon feature.

Exemples de code

curl "https://api.afrimap.ci/v1/isochrone?lat=5.3197&lng=-4.0167&time=15&mode=auto" \
  -H "X-AfriMap-Key: $AFM_KEY"

Testez-le

Essayer en direct

GET /v1/isochrone

Collez une clé sandbox afm_test_…. La requête part directement de votre navigateur vers le gateway, aucun proxy côté portail.

Minutes.

GET http://localhost:8090/v1/isochrone?lat=5.3197&lng=-4.0167&time=15
POST/v1/match

Snap a GPS trace to the road graph

Takes a raw GPS trace (noisy, possibly off-road) and returns the most likely sequence of road segments. Used post-trip for fare calculation and analytics.

Corps de la requête

Schéma : MatchRequest

JSONExemple
{
  "shape": [
    {
      "lat": 5.3197,
      "lng": -4.0167,
      "time": 1712000000
    },
    {
      "lat": 5.3223,
      "lng": -4.0142,
      "time": 1712000030
    },
    {
      "lat": 5.326,
      "lng": -4.011,
      "time": 1712000060
    }
  ],
  "mode": "auto"
}

Réponses

  • 200Matched trace.

Exemples de code

curl -X POST https://api.afrimap.ci/v1/match \
  -H "X-AfriMap-Key: $AFM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "shape": [
      {"lat":5.3197,"lng":-4.0167,"time":1712000000},
      {"lat":5.3223,"lng":-4.0142,"time":1712000030},
      {"lat":5.3260,"lng":-4.0110,"time":1712000060}
    ],
    "mode": "auto"
  }'
POST/v1/optimize

Trip optimisation (TSP)

Given an ordered list where the first point is origin, last is destination, and middle points are stops to visit in any order, returns the optimal stop sequence and the resulting route.

Corps de la requête

Schéma : OptimizeRequest

Réponses

  • 200Optimised trip.

Exemples de code

curl -X POST https://api.afrimap.ci/v1/optimize \
  -H "X-AfriMap-Key: $AFM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "locations": [
      {"lat":5.3197,"lng":-4.0167},
      {"lat":5.3480,"lng":-3.9904},
      {"lat":5.3364,"lng":-4.0694},
      {"lat":5.3197,"lng":-4.0167}
    ],
    "mode": "auto"
  }'