Modifier les dates
Décaler l’enlèvement ou la livraison, sur l’aller comme sur le retour, jambe par
jambe.
Options
Ajouter ou retirer une option ; le prix est recalculé automatiquement.
Refacturation
Changer le prix HT facturé au client pour une jambe, avec garde-fous et historique.
Annulation
Annuler une mission avant le départ du véhicule, avec le barème de frais de
l’espace client.
Toutes les routes ci-dessous sont scopées au groupe de votre clé. Une mission qui
n’appartient pas à votre groupe renvoie
404 Not Found (jamais 403). Les
mutations exigent le scope transports:write.1. Modifier les dates (par jambe)
Une mission a jusqu’à quatre jambes : l’enlèvement et la livraison de l’aller, et — pour un aller-retour — l’enlèvement et la livraison du retour. Vous modifiez chacune indépendamment viaPATCH /transports/{id}/dates.
Clés de jambe
object
requis
Carte des jambes à modifier (au moins une). Les clés possibles sont :
Chaque valeur est un objet
{ date, start_time, end_time }.string
Date au format ISO
YYYY-MM-DD (ex. 2026-07-02).string
Début de la fenêtre horaire (ex.
09:00).string
Fin de la fenêtre horaire (ex.
12:00).boolean
défaut:"true"
Si
false, le client n’est pas notifié du changement. Par défaut, seules les
jambes réellement modifiées déclenchent une notification.Vous pouvez envoyer les quatre jambes en une requête : seules celles dont la
date/horaire change effectivement déclencheront une notification. Inutile de
pré-filtrer côté client.
Comme toute écriture,
PATCH /dates renvoie un 409 Conflict si la
fenêtre de modification est fermée (mission
partie, J+0 ou au-delà, ou annulée). Voir l’encart « Fenêtre de modification »
en tête de page.Exemple — décaler l’enlèvement aller
200 :
string
Identifiant de la mission.
string[]
Liste des jambes effectivement modifiées (et donc, sauf
notify: false,
notifiées au client).transport.dates_updated avec un
payload { id, updated_legs }.
Majoration « dernier moment » (express)
Une mission dont l’enlèvement est imminent est majorée automatiquement sur le prix client. Aucun paramètre à passer : la majoration est calculée et appliquée par le serveur. La majoration s’applique dès que l’enlèvement tombe dans la zone « dernier moment » :Le taux par défaut est de +25 %, configurable par groupe. La majoration
porte uniquement sur le prix client : elle ne touche JAMAIS la
rémunération du convoyeur.
- à la création de la mission, si l’enlèvement est déjà imminent (le
pricerenvoyé parPOST /transportsinclut alors la majoration) ; - au changement de date via
PATCH /dates:- rapprocher l’enlèvement dans la zone « dernier moment » ajoute la majoration ;
- éloigner un enlèvement qui y était l’annule (le prix client redescend).
GET /transports/{id}/price-history. Le motif y vaut « Majoration express … »
lors de l’ajout, et « Annulation majoration express » lors du retrait.
2. Ajouter ou retirer une option
Les options (par exemple un nettoyage, un plein de carburant, une prise de rendez-vous) sont rattachées à la mission par une clé d’option (option_key).
Ajouter ou retirer une option recalcule automatiquement le prix de la mission.
Ajouter une option
POST /transports/{id}/options
string
requis
Clé de l’option à ajouter (
key renvoyé par GET /options). Le prix est celui
de la grille de votre groupe — vous ne le transmettez pas. Une clé inconnue
renvoie 422 avec code: "unknown_option".string
défaut:"aller"
Jambe visée :
aller ou retour. Toute autre valeur renvoie 422
(errors: [{ "field": "leg", "error": "invalid" }]) ; retour sur une mission
sans trajet retour renvoie 422 avec code: "no_return_leg". Mêmes règles pour
le paramètre ?leg= du retrait d’option.object
Obligations de l’option, décrites par
requirements dans GET /options :
renter (identifiant du loueur partenaire), link ou pin selon le loueur
(PV dématérialisé), comment (consigne libre), accessories (liste
{ id, name, source } pour la vérification des accessoires),
pending_documents (documents que vous déposerez juste après, ex. PV_PAPIER).
Une obligation manquante renvoie 422 avec code: "requirements_not_met" et
le champ concerné dans errors[].field.Le catalogue complet, avec vos prix et les obligations de chaque option, est
servi par
GET /options. La table ci-dessous n’est qu’un
aide-mémoire.Clés d’option disponibles
Utilisez l’une de ces clés (option_key). Le libellé est donné à titre indicatif ;
le prix indiqué est le prix client de référence de l’option (le montant
réellement facturé dépend de la grille négociée de votre groupe). S’y ajoutent
PV_PAPIER, PV_DEMATERIALISE et CHECK_ACCESSORY, qui portent des obligations
(voir le guide Options).
200 :
string
Clé de l’option ajoutée.
number | null
Nouveau prix de la mission après recalcul.
number | null
Variation de prix induite par l’ajout de l’option.
Retirer une option
DELETE /transports/{id}/options/{option_key}
La clé d’option fait partie du chemin et doit être URL-encodée.
200 :
number | null
Nouveau prix de la mission après retrait de l’option.
number | null
Variation de prix (négative ici, l’option étant retirée).
Ajouter comme retirer une option émet l’événement
transport.price_adjusted.L’ajout (
POST .../options) renvoie un 409 Conflict si la
fenêtre de modification est fermée (mission
partie, J+0 ou au-delà, annulée) ou si la mission est déjà payée / facturée.
Le DELETE est idempotent : retirer une option déjà absente n’est pas une
erreur, et un même Idempotency-Key rejoue la même réponse.3. Refacturer une jambe
La refacturation modifie le prix HT facturé au client pour une jambe donnée. Contrairement aux options, elle force un nouveau prix au lieu d’appliquer la grille — d’où l’exigence d’un motif et la traçabilité intégrale.POST /transports/{id}/price-adjustments
string
défaut:"aller"
Jambe concernée :
aller ou retour. Toute autre valeur renvoie 422
(errors: [{ "field": "leg", "error": "invalid" }]). retour sur une mission
sans trajet retour renvoie 422 avec code: "no_return_leg" (aucun prix
n’est modifié).number
requis
Nouveau prix HT facturé au client (nombre ≥ 0). Obligatoire.
string
requis
Motif de la refacturation. Obligatoire — il est conservé dans l’historique.
Exemple
201 :
string
Identifiant de la mission.
string
Jambe refacturée (
aller ou retour).number | null
Ancien prix HT facturé au client, avant ajustement.
number | null
Nouveau prix HT facturé au client, après ajustement.
string
Devise des montants — toujours
EUR.Garde-fou : jambe déjà payée ou facturée
Ce garde-fou est appliqué à deux niveaux : un contrôle rapide en amont, puis
un second contrôle au moment de l’écriture. Le
detail peut donc varier (et
être en français) selon le niveau qui a bloqué : branchez votre logique sur le
status (409) et le code (leg_invoiced), jamais sur le texte de detail.
Une mission annulée renvoie aussi 409. Si l’état de facturation ne peut pas
être vérifié sur le moment, la refacturation (comme l’ajout d’option) est
refusée sans rien modifier : 502 avec code: "billing_unavailable", ou 500
avec une reference si la vérification échoue dès l’entrée de l’API. Dans les
deux cas, réessayez dans un instant.Historique des refacturations
Chaque refacturation est tracée. Consultez l’historique complet d’une mission viaGET /transports/{id}/price-history.
200 :
object[]
Liste des changements de prix, chacun avec
leg, old_price_ht, new_price_ht,
motif et created_at. Seul le prix HT facturé au client est exposé.Une refacturation émet l’événement
transport.price_adjusted avec un payload
{ id, leg, old_price_ht, new_price_ht, motif }.4. Annuler la mission
POST /transports/{id}/cancel
L’annulation est possible tant que le véhicule n’est pas parti (statuts
publics scheduled et assigned). Exception : une mission assigned dont
l’attribution au convoyeur est encore en cours de confirmation est refusée
(409 not_cancellable) ; contactez le support si l’annulation est urgente. La
mission n’est pas supprimée : elle passe au
statut cancelled (cancelled: true), reste lisible via
GET /transports/{id} et apparaît dans GET /transports?status=cancelled. Sur un
aller-retour, le retour est annulé avec l’aller s’il n’est pas déjà terminé
(return_included).
string
Motif d’annulation. Optionnel — le corps de la requête l’est aussi.
Frais d’annulation
Le barème est le même que dans l’espace client. Il est calculé sur la date d’enlèvement de l’aller, à l’heure de Paris, en jours ouvrés (lundi à vendredi) :
Le montant facturé (
penalty.client_charge_ht) vaut le prix HT de la mission —
retour compris quand return_included est true — multiplié par
penalty.ratio.
Après l’annulation, ces frais se relisent sur la mission : price.amount_ht de
GET /transports/{id} (et return_trip.price.amount_ht si le retour est inclus)
vaut le montant facturé pour chaque jambe, et GET /transports/{id}/price-history
trace le passage de l’ancien prix au prix d’annulation.
200 :
string
Identifiant de la mission.
string
Toujours
cancelled en cas de succès.object
Frais d’annulation (prix client HT uniquement).
boolean
true si le trajet retour a été annulé avec l’aller (et compté dans les frais).
false pour un aller simple.Garde-fou : mission plus annulable
status (409) et le code, pas
sur le texte du detail.
Un 502 sur une annulation laisse son issue incertaine (service qui n’a pas
répondu à temps, ou annulation non confirmée) : relisez la mission via
GET /transports/{id} avant de réessayer. Si elle est déjà cancelled, un nouvel
essai recevrait 409 already_cancelled ; ses frais se lisent dans
price.amount_ht.
L’annulation émet, peu après et une seule fois, l’événement
transport.cancelled avec un payload { id, transport_id, cancelled_at },
ainsi qu’un transport.status_changed vers cancelled. Les frais n’y figurent
pas : conservez la réponse 200 ci-dessus. Le motif (reason) n’est renvoyé
ni par l’événement ni par la réponse : gardez-le de votre côté si vous en avez
besoin.Récapitulatif des garde-fous
409 sur dates / options / documents (fenêtre de modification)
409 sur dates / options / documents (fenêtre de modification)
La mission est partie (J+0 ou au-delà, ou statut public
in_transit et
suivants), ou annulée. Tant que ce verrou est fermé, on ne peut plus modifier
les dates, les options ni les documents. Vérifiez l’état via GET /transports/{id}.409 sur une refacturation
409 sur une refacturation
La jambe ciblée est déjà payée ou facturée (
code: leg_invoiced) — pour un
aller-retour facturé en une fois, le retour compte comme facturé — ou la
mission est annulée. Le prix est figé pour des raisons comptables : aucune
refacturation n’est possible.409 sur une annulation
409 sur une annulation
La mission n’est plus annulable : seules les missions avant le départ
(
scheduled / assigned) le sont. Une mission partie ou terminée — ou dont
l’attribution au convoyeur est encore en cours de confirmation — renvoie
409 not_cancellable, une mission déjà annulée 409 already_cancelled.
Après un 502 sur une annulation, un nouvel essai qui reçoit
already_cancelled signifie que la première tentative avait abouti.404 au lieu de 403
404 au lieu de 403
La mission n’appartient pas au groupe de votre clé. Pour ne pas révéler son
existence, l’API renvoie
404 plutôt que 403. Vérifiez l’id et la clé
utilisée.422 sur la validation
422 sur la validation
Un champ requis manque (par exemple
motif ou new_price sur une
refacturation), leg n’est ni aller ni retour, les dates sont
incohérentes (livraison avant enlèvement, retour avant aller, date dans le
passé), ou une jambe retour est visée sur une mission sans trajet retour
(code: no_return_leg). detail résume l’erreur ; lisez le tableau errors[]
du corps problem+json pour le détail champ par champ.Le convoyeur doit valider vos modifications
Dès qu’un convoyeur est attribué à la mission et qu’elle n’est pas encore partie, une modification de dates ou d’options ne s’applique pas dans son dos : elle lui est soumise. Il reçoit une notification et doit accepter ou refuser les nouvelles modalités depuis l’application MED. Chaque réponse vous le dit :
Pour le suivre : l’événement
transport.driver_validation_requested est émis à
la création de la demande, et le statut de la mission repasse en scheduled
(non attribuée) si le convoyeur refuse.
Le champ driver_validation de la requête est réservé aux administrateurs
MED : l’envoyer avec une clé partenaire renvoie 403 forbidden_field. Il n’est
pas ignoré en silence, précisément pour qu’une intégration ne croie jamais avoir
désactivé cette validation.
Étapes suivantes
Webhooks
Recevez
transport.dates_updated, transport.price_adjusted et
transport.cancelled en temps réel sur votre endpoint signé.Suivre une mission
Statut public, positions GPS du convoyeur et documents/PV de la mission.
Gestion des erreurs
Le format RFC 9457 et la liste des codes de conflit à gérer.
