POST /pricing calcule un tarif sans créer de mission. C’est l’endpoint à appeler pour afficher un prix à vos utilisateurs, comparer des options, ou valider un budget avant de passer commande. Aucune ressource n’est créée, rien n’est facturé.
Le prix renvoyé par /pricing applique exactement la même grille que POST /transports. Un devis et la création qui suit, sur un trajet identique, donnent le même tarif. Voir Le prix de création est cohérent.

La grille tarifaire dépend de votre groupe

Chaque clé API est rattachée à un groupe (flotte, concession, loueur). Ce groupe porte une grille tarifaire négociée : c’est elle qui détermine le prix. Vous n’avez rien à transmettre pour la sélectionner — elle est déduite de votre X-Api-Key. Concrètement, le moteur de tarification combine plusieurs facteurs :

Distance

Les adresses d’enlèvement et de livraison sont géocodées, puis la distance routière est calculée. C’est le principal déterminant du prix.

Type de véhicule

VP, VU, VUL… chaque catégorie a son barème. Un véhicule électrique applique une majoration qui peut dépendre de la distance.

Plateau

Le transport sur plateau (véhicule non roulant) suit un barème distinct, activé par le drapeau plateau de la requête.

Options

Lavage, carburant, prestations additionnelles… chaque option passée dans options est intégrée au prix HT renvoyé.

Aller-retour

Un trajet retour applique la remise retour négociée de votre groupe, détaillée dans le champ return_trip de la réponse.

Supplément localisation

International ou zones spécifiques (ex. Corse) ajoutent un supplément selon le pays et le code postal, intégré au prix HT renvoyé.

Avant de commencer

X-Api-Key
string
requis
Votre clé API (med_live_… en production, med_test_… en test). Elle détermine le groupe — donc la grille appliquée.
Le scope transports:read n’est pas requis pour /pricing : seule une clé valide (non révoquée, non expirée) est nécessaire. Une clé invalide renvoie 401.
export BASE="https://api.myexpressdriver.com/v1"
export MED_API_KEY="med_live_xxxxxxxxxxxxxxxxxxxx"

Corps de la requête

pickup
string | object
requis
Point d’enlèvement. Une chaîne d’adresse ("10 Rue de Rivoli, 75004 Paris") ou un objet { address }. L’adresse est géocodée pour calculer la distance.
delivery
string | object
requis
Point de livraison, même format que pickup.
vehicle
object
Caractéristiques du véhicule.
plateau
boolean
true pour un transport sur plateau. Le tarif plateau est toujours renvoyé dans la réponse, que ce drapeau soit posé ou non.
options
string[]
Liste des clés d’options à inclure dans l’estimation.
return_trip
boolean | object
true (ou un objet décrivant le retour) pour estimer un aller-retour. Le détail du retour apparaît dans le champ return_trip de la réponse.
billing
object
Informations de facturation simplifiées. Optionnel pour une estimation : la grille vient du groupe de la clé, pas de la facturation.
car est accepté comme alias de vehicle, et returnTrip comme alias de return_trip. Utilisez de préférence les formes en snake_case.

Exemple de devis

curl -s -X POST "$BASE/pricing" \
  -H "X-Api-Key: $MED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "pickup":   { "address": "10 Rue de Rivoli, 75004 Paris" },
    "delivery": { "address": "1 Place Bellecour, 69002 Lyon" },
    "vehicle":  { "type": "VP", "electric": false },
    "plateau":  false,
    "options":  []
  }'

Réponse 200

{
  "price_ht": 180.5,
  "currency": "EUR",
  "distance_km": 465.2,
  "pickup":   { "address": "10 Rue de Rivoli, 75004 Paris, France", "lat": 48.8557, "lng": 2.3589, "place_id": "ChIJ7Qq9bF9u5kcRYJSMaMOCCwQ" },
  "delivery": { "address": "Place Bellecour, 69002 Lyon, France",   "lat": 45.7578, "lng": 4.8320, "place_id": "ChIJ65aN5w7q9EcR_HhwT2N0gJg" },
  "return_trip": null
}

Comprendre la réponse

price_ht
number
Prix HT du transport facturé au client. C’est le tarif de référence à afficher.
currency
string
Devise des montants — toujours EUR.
distance_km
number
Distance routière estimée, en kilomètres, issue du géocodage des deux adresses.
pickup
object
Adresse d’enlèvement résolue par le géocodeur : address normalisée, lat, lng et place_id (référence Google déterministe). Vérifiez-la pour confirmer que le point retenu correspond bien à ce que vous visiez avant de créer la mission.
delivery
object
Adresse de livraison résolue, même structure que pickup.
return_trip
object | null
Détail du trajet retour quand return_trip est demandé, sinon null. Contient price_ht, distance_km, et les adresses résolues pickup (= livraison aller) et delivery (destination du retour).
Tous les montants sont HT, en euros. La rémunération convoyeur, les pénalités et les champs internes ne sont jamais exposés au-delà de ce que renvoie ce devis.
Les adresses sont en texte libre géocodé côté serveur : "paris" est résolu vers le centre-ville, pas vers une rue précise. Soyez le plus spécifique possible (numéro + rue + code postal + ville) et contrôlez toujours pickup/delivery dans la réponse — une adresse ambiguë fausse la distance, donc le prix.

Variantes de devis

Un véhicule électrique peut appliquer une majoration qui dépend de la distance.
{
  "pickup":   { "address": "10 Rue de Rivoli, 75004 Paris" },
  "delivery": { "address": "1 Place Bellecour, 69002 Lyon" },
  "vehicle":  { "type": "VP", "electric": true }
}

Le prix de création est cohérent

La grille appliquée par POST /pricing est identique à celle appliquée par POST /transports. Un devis fait foi : créez la mission sur le même trajet, le même véhicule et les mêmes options, et vous obtenez le même prix.
Vous pouvez donc présenter le devis à votre utilisateur, puis créer la mission en toute confiance sans craindre un écart de tarif. La réponse de création renvoie le prix retenu dans son champ price.
{
  "id": "-O9xAbCdEf",
  "transport_id": "M-54321",
  "status": "scheduled",
  "price": { "amount_ht": 180.5, "currency": "EUR" }
}

Gestion des erreurs

Les erreurs suivent la RFC 9457 (Content-Type: application/problem+json). Branchez votre logique sur status et title, pas sur le texte de detail.
Clé manquante, inconnue, révoquée ou expirée. Vérifiez l’en-tête X-Api-Key.
{
  "type": "about:blank",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Invalid API key."
}
Un champ requis manque (ex. pickup ou delivery). Le tableau errors[] précise le champ en cause.
{
  "type": "about:blank",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "pickup is required.",
  "errors": [
    { "field": "pickup", "error": "required" }
  ]
}
Respectez l’en-tête Retry-After (en secondes) et appliquez un back-off.
{
  "type": "about:blank",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Rate limit (key) exceeded."
}
Échec d’un service amont (relai de tarification). L’estimation n’a aucun effet de bord : vous pouvez réessayer sans risque.

Étapes suivantes

Créer une mission

Transformez un devis en mission réelle avec POST /transports.

Authentification

Clés API, scopes et isolation par groupe.