Idempotence
Une coupure réseau pendant POST /sessions, et vous ne savez plus si la session existe : la rejouer sans précaution enverrait un second SMS au client. L’en-tête Idempotency-Key règle ce cas.
Les requêtes POST acceptent l’en-tête Idempotency-Key (255 caractères au plus), selon le
brouillon de l’IETF.
Rejouée dans les 24 heures avec la même clé et le même corps, la requête renvoie la réponse d’origine
sans rien refaire : pas de second SMS sur une reprise réseau. Même clé, autre corps :
409 idempotency_conflict.
Les routes concernées
Section intitulée « Les routes concernées »La spec déclare l’en-tête sur ces routes :
- POST
/sessions: créer une session - POST
/sessions/{session_id}/resend: renvoyer l'invitation - POST
/sessions/{session_id}/end: terminer une session - POST
/sessions/{session_id}/simulate: simuler le parcours du client (mode test) - POST
/webhook_endpoints: créer un abonnement - POST
/webhook_endpoints/{endpoint_id}/test: envoyer un événement de test - POST
/webhook_endpoints/{endpoint_id}/rotate_secret: renouveler le secret
Bien choisir la clé
Section intitulée « Bien choisir la clé »- Une clé par opération métier : un UUID tiré au moment où vous décidez de créer la session, gardé avec la tâche qui la crée.
- La même clé pour rejouer cette opération, après un délai dépassé, une coupure ou un
5xx. - Jamais la même clé pour un autre corps : l’API répond
409 idempotency_conflict.
import { randomUUID } from 'node:crypto';
// Tirée une fois, gardée avec la tâche : chaque nouvelle tentative la réutilise.const cle = randomUUID();
for (let tentative = 1; tentative <= 3; tentative++) { try { const reponse = await fetch('https://api.vizalia.ai/v1/sessions', { method: 'POST', headers: { Authorization: `Bearer ${process.env.VIZALIA_API_KEY}`, 'Content-Type': 'application/json', 'Idempotency-Key': cle, }, body: JSON.stringify({ channel: 'sms', to: '+33612345678', reference: 'TICKET-48213' }), signal: AbortSignal.timeout(15_000), }); if (reponse.status < 500) return await reponse.json(); } catch { // Délai dépassé ou coupure : on rejoue avec la même clé. } await new Promise((fin) => setTimeout(fin, tentative * 2_000));}import timeimport uuid
import requests
# Tirée une fois, gardée avec la tâche : chaque nouvelle tentative la réutilise.cle = str(uuid.uuid4())
for tentative in range(1, 4): try: reponse = requests.post( "https://api.vizalia.ai/v1/sessions", headers={"Authorization": f"Bearer {CLE_API}", "Idempotency-Key": cle}, json={"channel": "sms", "to": "+33612345678", "reference": "TICKET-48213"}, timeout=15, ) if reponse.status_code < 500: break except requests.RequestException: pass # Délai dépassé ou coupure : on rejoue avec la même clé. time.sleep(tentative * 2)