POST /transports planifie un transport de véhicule, le rend visible côté
convoyeurs, et déclenche l’événement webhook transport.created.
La mission créée porte le statut public
scheduled : elle est planifiée et
en attente d’attribution d’un convoyeur. Vous suivrez ensuite sa progression via
les statuts assigned, in_transit, awaiting_documents, under_review puis
completed.Prérequis
Clé API
Une clé portant le scope
transports:write, envoyée dans l’en-tête
X-Api-Key: med_live_....Adresses d'enlèvement et de livraison
Les champs
pickup et delivery sont requis, chacun avec adresse, date,
créneau (ou need_appointment: true) et contact complet (nom, téléphone,
e-mail).Facturation
Le bloc
billing est requis, avec raison sociale, e-mail et adresse —
même si vous désignez l’entité par entity_id.Clé d'idempotence
Indispensable : un
Idempotency-Key unique par mission, pour pouvoir
réessayer sans jamais créer de doublon.Les champs du corps de la requête
Le corps est un objet JSON. Sont requis : le véhicule (car, ou son alias
vehicle) avec son immatriculation registration ; pickup et delivery, chacun
avec address, date, contact (name, phone, mail) et le créneau
start_time / end_time (sauf need_appointment: true) ; billing avec
company_name, address et email. Tous les autres champs sont optionnels.
Ces exigences valent pour la création. L’estimation
POST /pricing se
contente des adresses (et du véhicule pour le gabarit).Champs racine
string
Type de transport. Valeurs usuelles :
livraison, restitution,
conciergerie. En l’absence de valeur, le transport est traité comme une
livraison standard.boolean
défaut:"false"
Indique un transport sur plateau (camion porte-véhicule) plutôt qu’en
roulant. Impacte la tarification.
boolean
défaut:"false"
Indique que le carburant est remboursé au convoyeur sur cette mission.
boolean
défaut:"false"
Véhicule circulant sous plaques W garage (immatriculation provisoire
professionnelle).
string[]
Liste des clés d’options à appliquer à la mission (ex. lavage, plein de
carburant). Les clés disponibles dépendent de la grille de votre groupe.
string
Note libre attachée à la mission (consignes particulières, référence interne).
car — le véhicule
object
requis
Caractéristiques du véhicule transporté.
Dans le contrat OpenAPI, l’objet véhicule est nommé
vehicle et accepte aussi
type, vin, brand et model. car est l’alias documenté côté guide ;
les deux pointent vers le même objet véhicule. Préférez vehicle si vous générez
votre client directement depuis l’OpenAPI.pickup — point d’enlèvement
object
requis
Lieu, créneau et contact pour l’enlèvement du véhicule.
delivery — point de livraison
object
requis
Lieu, créneau et contact pour la livraison du véhicule. Mêmes propriétés et
mêmes exigences que
pickup.billing — facturation
object
requis
Informations de facturation de la mission.
company_name, address et email
sont toujours requis, même avec entity_id : s’il en manque un, la
création est refusée en 422 et errors[] nomme chaque champ manquant
(billing.company_name, billing.address, billing.email).return_trip — aller-retour
boolean | string | object
Décrit la jambe retour. Omettez (ou
false) pour un aller simple. Trois formes :true→ A→B→A : retour vers le lieu d’enlèvement de l’aller."adresse"(chaîne) → A→B→C : retour vers cette adresse de destination.- objet → forme complète (ci-dessous), pour préciser véhicule / contacts / horaires du retour.
true ou chaîne), le retour reprend le véhicule de l’aller,
la date de livraison de l’aller et le contact de livraison de l’aller (à
défaut, celui d’enlèvement), sans créneau : il est créé en attente de
rendez-vous.Le retour n’a pas d’adresse de départ à renseigner. Il part
automatiquement du lieu de livraison de l’aller (le convoyeur repart de là
où il vient de livrer). Vous ne précisez donc que la destination du retour
(forme courte
"adresse", ou return_trip.delivery) — jamais un point de départ.Exemple — aller simple
Exemple — aller-retour
Pour un aller-retour, ajoutez le blocreturn_trip avec le véhicule et le point
de livraison du retour.
Réponse 201 Created
En cas de succès, l’API renvoie 201 avec l’identifiant de la mission, son
statut, le prix calculé et les adresses retenues.
string
Identifiant technique de la mission (
offer_id). À utiliser dans tous les
appels ultérieurs : GET /transports/{id}, suivi GPS, documents, etc.string | null
Référence métier lisible de la mission (ex.
M-54321). Vaut null dans
cette réponse : elle est attribuée juste après la création. Lisez-la via
GET /transports/{id}.string
Statut public de la mission. À la création, vaut toujours
scheduled.string | null
Prix HT facturé pour l’aller, sous forme de chaîne décimale (ex.
"407.44", ou "180" sans décimales), majorations comprises. Convertissez-la
en nombre côté client. Le prix détaillé (price.amount_ht,
price.surcharge_ht, price.currency) et celui du retour
(return_trip.price) se lisent via GET /transports/{id}.object | null
Entité(s) de facturation MED posée(s) sur la mission :
entity_id (aller) et
return_entity_id (retour, null sans trajet retour).object
Adresse d’enlèvement résolue (géocodée) effectivement enregistrée :
address normalisée, lat, lng, place_id. Contrôlez-la pour vérifier que
le point retenu est bien celui visé.object
Adresse de livraison résolue, même structure que
pickup.object | null
Pour un aller-retour : adresses résolues
pickup (= livraison de l’aller) et
delivery (destination du retour). null sur un aller simple.Conservez l’
id renvoyé : c’est lui qui identifie la mission pour le suivi, la
modification des dates, les options et l’annulation.Idempotence
La création de mission est l’opération la plus sensible aux doublons : un appel qui échoue côté réseau peut avoir réussi côté serveur. Pour vous protéger, envoyez systématiquement un en-têteIdempotency-Key (par exemple un UUID v4
que vous générez).
Première requête
Première requête
Exécutée normalement. La réponse est mise en cache et associée à la clé.
Même clé + même corps
Même clé + même corps
La réponse en cache est rejouée à l’identique, avec l’en-tête
Idempotent-Replayed: true. Une seule mission est créée.Même clé + autre requête
Même clé + autre requête
L’API renvoie
409 Conflict avec code: idempotency_key_reused : la clé a
déjà servi pour une requête différente (autre corps, autre route ou autre
mission).Échec 5xx ou 502 relay_timeout
Échec 5xx ou 502 relay_timeout
Les réponses
5xx ne sont pas mises en cache : vous pouvez réessayer avec la
même clé et le même corps. Un 502 avec code: relay_timeout signifie que la
mission a pu être créée malgré l’erreur : le nouvel essai vous la renvoie
(201 identique) au lieu d’en créer une seconde.Issue inconnue (outcome_unknown: true)
Issue inconnue (outcome_unknown: true)
Un
502, ou un 409 request_in_progress sans Retry-After, peut porter
outcome_unknown: true : la création avait commencé quand l’erreur est
survenue, et son issue est inconnue. Cette situation ne se résout pas par un
nouvel essai. Ne renvoyez pas la commande : vérifiez d’abord par
GET /transports (avec since, ou en cherchant votre référence de commande)
si la mission existe, ou contactez le support.Création encore en cours (409 request_in_progress)
Création encore en cours (409 request_in_progress)
Si vous réessayez pendant que la première création est encore en traitement,
l’API répond
409 avec code: request_in_progress et un en-tête
Retry-After (5 s). Rien n’est recréé : patientez puis réessayez avec la même
clé. Sans Retry-After et avec outcome_unknown: true, voir ci-dessous.Erreurs
Les erreurs suivent la RFC 9457 (Content-Type: application/problem+json).
Exemple de
422 lorsqu’un champ requis manque — detail résume, errors[]
détaille champ par champ :
Étapes suivantes
Suivre une mission
Récupérer le détail, les positions GPS et l’ETA du convoyeur.
Modifier les dates
Ajuster les créneaux d’enlèvement et de livraison, par jambe.
Recevoir les événements
S’abonner aux webhooks signés (
transport.created, transport.status_changed…).