POST peut échouer après avoir été
exécutée côté serveur : la mission est créée, mais vous ne recevez jamais la
réponse. Si vous réessayez naïvement, vous créez un doublon.
L’idempotence résout ce problème. En attachant un en-tête Idempotency-Key
à vos requêtes mutantes, vous garantissez que l’opération ne produit son effet
qu’une seule fois, quel que soit le nombre de fois où vous la rejouez.
L’idempotence est le filet de sécurité de la création de mission. Combinée à la
réconciliation par webhook, elle rend votre intégration
robuste face aux pannes transitoires.
En bref
En-tête
Idempotency-Key: <votre-clé> — une chaîne libre que vous générez
(un UUID v4 est idéal).Portée
Les
POST mutants : toutes les créations (mission, duplication,
documents) en priorité, mais aussi refacturations, options, annulation, dates.Durée de vie
Une clé est mémorisée 24 h. Au-delà, la même clé est traitée comme neuve.
Rejeu
Une réémission identique renvoie la réponse en cache avec
l’en-tête
Idempotent-Replayed: true.Comment l’utiliser
1
Générez une clé unique par opération métier
Une clé d’idempotence représente une intention : « créer cette mission-ci ».
Générez une nouvelle clé pour chaque opération distincte — un UUID v4 fait
parfaitement l’affaire.
2
Attachez-la à la requête mutante
Ajoutez l’en-tête
Idempotency-Key à votre POST (en plus de
X-Api-Key).3
Rejouez la même clé en cas d'incertitude
Si la requête échoue par timeout, erreur réseau,
5xx ou 502 avec
code: relay_timeout, réémettez-la à l’identique (même clé, même corps).
Une réponse déjà obtenue est rejouée depuis le cache. Après une erreur, la
requête est relancée : la création de mission et le dépôt de documents
sont alors dédoublonnés (la mission ou les documents déjà enregistrés vous sont
renvoyés) ; les autres modifications (dates, options, refacturation,
annulation) ne le sont pas, mais sont idempotentes par nature ou renvoient un
409 si elles ont déjà été appliquées — relisez la mission en cas de doute.
Exception : une réponse avec outcome_unknown: true ne se rejoue pas, vérifiez
d’abord.Exemple : créer une mission de façon sûre
L’en-têteIdempotency-Key est posé une fois ; les deux mêmes appels ne créent
qu’une seule mission.
201 est identique à chaque rejeu (extrait) :
price est le prix HT de l’aller en chaîne décimale ; transport_id vaut
null à la création (la référence M-xxxxx est attribuée juste après et se lit
via GET /transports/{id}).
Sémantique détaillée
Le tableau ci-dessous décrit comment le serveur traite une clé selon le scénario.Le rejeu : Idempotent-Replayed
Quand le serveur renvoie une réponse en cache, il ajoute l’en-tête de réponse :
502 relay_timeout : la réponse renvoie
alors ce qui avait déjà été créé.
Vérifiez
Idempotent-Replayed après chaque retry : sa présence confirme que
votre réémission n’a pas créé de doublon.Conflit de clé : 409
Réutiliser une même clé pour une requête différente — autre corps, autre
route ou autre mission — est une erreur de votre côté : la clé identifie une
opération précise, elle ne peut pas en désigner deux. Le serveur répond alors
409 Conflict au format RFC 9457
(application/problem+json) :
Les erreurs serveur ne sont pas cachées
Une réponse5xx (par exemple 502 Bad Gateway) n’est pas mémorisée. La
clé reste attachée à l’empreinte de la requête, ce qui rend le retry sûr :
réémettez exactement la même requête (même clé, même corps) et elle est relancée
sans risque de doublon. Si le corps a changé entre-temps (re-sérialisation,
champ ajouté), le retry est refusé en 409 idempotency_key_reused plutôt que de
créer une seconde opération.
Logique de retry recommandée
Quand l’utiliser
L’idempotence protège les opérations qui créent ou modifient un état et dont un doublon aurait des conséquences. Posez systématiquement uneIdempotency-Key
sur :
Création de mission — POST /transports
Création de mission — POST /transports
Le cas d’usage prioritaire. Un doublon créerait deux missions facturables.
C’est ici que l’idempotence apporte le plus de valeur.
Refacturation — POST /transports/{id}/price-adjustments
Refacturation — POST /transports/{id}/price-adjustments
Évite d’appliquer deux fois le même changement de prix lors d’un retry.
Options — POST /transports/{id}/options
Options — POST /transports/{id}/options
Empêche d’ajouter la même option (et de recalculer le prix) en double.
Annulation — POST /transports/{id}/cancel
Annulation — POST /transports/{id}/cancel
Après une réponse
200, un retry avec la même clé rejoue cette réponse (frais
compris). Après un 502 (relay_timeout), en revanche, l’annulation a pu
aboutir sans que la réponse soit mémorisée : le retry, même clé ou pas, reçoit
alors 409 (code: already_cancelled) et n’a aucun effet. Lisez les frais
appliqués via GET /transports/{id} (price.amount_ht) ou
GET /transports/{id}/price-history.Dates — PATCH /transports/{id}/dates
Dates — PATCH /transports/{id}/dates
Évite de réémettre une notification de changement d’horaires au client.
Documents — POST /transports/{id}/documents
Documents — POST /transports/{id}/documents
Empêche l’ajout en double des mêmes pièces jointes à la mission. Après un
502 relay_timeout, un retry avec la même clé ne devrait pas créer de doublon.Duplication — POST /transports/{id}/duplicate
Duplication — POST /transports/{id}/duplicate
Une mission ne se duplique qu’une fois : après un
502 relay_timeout, un
nouvel essai renvoie 409 (code: already_duplicated, avec duplicated_to)
si la duplication a abouti. Lisez la mission créée via duplicated_to.Bonnes pratiques
- Une clé par intention métier. Générez la clé avant le premier envoi et conservez-la pour tous les retries de cette même opération. Ne réutilisez jamais une clé pour une opération différente.
- Persistez la clé côté client (file d’attente, base) jusqu’à obtenir une réponse définitive, afin de pouvoir rejouer après un crash de votre processus.
- Branchez votre logique sur le code HTTP (
status), pas sur le texte dedetailqui peut évoluer. - TTL 24 h : une clé expirée n’offre plus de protection. Une opération reprise au-delà de 24 h sera traitée comme nouvelle — utilisez une clé fraîche.
Étapes suivantes
Démarrage rapide
Créez votre première mission de bout en bout, avec idempotence.
Format des erreurs
Comprenez les réponses
409, 422 et 5xx (RFC 9457).Webhooks
Réconciliez les événements manqués et déduplisez côté consommateur.
