{"openapi":"3.1.0","info":{"title":"API Vitef","version":"1.2.0","description":"API de vitef.com : lettres administratives conformes, calculateurs, outils IA, envoi postal (lettre simple, recommandé, recommandé AR) avec suivi, preuves et webhooks.\n\nGuides, exemples (curl, JavaScript, Python) et tarifs : https://vitef.com/developpeurs/documentation\n\n## Authentification\n`Authorization: Bearer vf_test_…` (bac à sable) ou `vf_live_…` (production). Clés créées dans l’espace développeur (https://vitef.com/espace/api) ; la production s’ouvre après validation du compte. Appelez l’API depuis votre serveur : aucun en-tête CORS, une clé ne doit jamais se trouver dans un navigateur ou une application.\n\n## Droits des clés (scopes)\nChaque clé porte des droits `ressource:action` (`catalogue:read`, `letters:write`, `mailings:read`, `mailings:write`, `data:read`, `ai:write`, `requests:read`, `requests:write`) ; le droit exigé par chaque opération figure dans son exigence de sécurité. Sans lui : 403 `insufficient_scope`.\n\n## Idempotence\nEn-tête `Idempotency-Key` (UUID v4 recommandé) sur tout `POST` : pendant 24 h, la même requête renvoie la première réponse (`Idempotent-Replayed: true`), sans nouvel envoi ni débit. Autre requête avec la même clé : 422 `idempotency_key_reused` ; requête identique en cours : 409 `idempotency_in_progress`. Un envoi dont le dépôt n’est pas encore confirmé reste `paid` et est redéposé automatiquement, sans doublon.\n\n## Pagination\n`?limit=` (1 à 100, 20 par défaut) et `?cursor=` (valeur `nextCursor` de la page précédente) → `{ data, nextCursor, hasMore }`, du plus récent au plus ancien.\n\n## Bac à sable\nClé `vf_test_` : rien n’est posté ni facturé, IA simulée, preuves fictives, 1 000 appels par jour ; `POST /v1/test/mailings/{id}/advance` fait avancer un envoi pour recevoir ses webhooks.\n\n## Erreurs\n`{ \"error\": { \"code\", \"message\", \"details?\" } }`. Codes fréquents : `invalid_api_key`, `revoked_api_key` (401) ; `account_suspended`, `live_not_enabled`, `test_only`, `insufficient_scope` (403) ; `idempotency_in_progress` (409) ; `invalid_cursor` (400) ; `insufficient_balance` (402) ; `address_invalid`, `recipient_email_required`, `idempotency_key_reused` (422) ; `payload_too_large` (413, corps de plus de 1 Mo) ; `rate_limited`, `test_quota_exceeded` (429) ; `upstream_error` (502).\n\n## Limites\n120 requêtes par minute et par clé (en-têtes `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`).\n\n## Facturation\nCrédit **prépayé**, rechargé par carte, Apple Pay ou Google Pay depuis l’espace développeur (facture Stripe à chaque recharge). Chaque unité payante est débitée du solde avant exécution (402 `insufficient_balance` sinon, rien n’est exécuté) ; solde restant dans l’en-tête `X-Vitef-Balance` (centimes HT). Données et calculs : quota gratuit mensuel, puis 1 à 2 centimes. Montants en centimes d’euro **HT**.\n\n## Webhooks\nÉvénements `mailing.*` signés : en-tête `Vitef-Signature: t=<horodatage>,v1=<HMAC-SHA256(secret, \"<t>.<corps brut>\")>`.","contact":{"name":"vitef","email":"contact@vitef.com","url":"https://vitef.com/developpeurs"}},"servers":[{"url":"https://api.vitef.com","description":"Production"},{"url":"https://api-preprod.vitef.com","description":"Préproduction"},{"url":"http://localhost:8787","description":"Local"}],"tags":[{"name":"B2B (v1)","description":"Nos API (clé d’API, facturation à l’usage). Jamais de rupture sans nouvelle version majeure."}],"paths":{"/v1/ai/fill":{"post":{"operationId":"v1AiFill","summary":"Remplit les champs d’une lettre à partir d’une phrase (facturé à l’usage)","tags":["B2B (v1)"],"security":[{"apiKey":["ai:write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiFillRequest"}}}},"responses":{"200":{"description":"Valeurs extraites","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1AiFillResult"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/ai/letters":{"post":{"operationId":"v1AiLetters","summary":"Rédige une lettre sur mesure (facturé à l’usage)","tags":["B2B (v1)"],"security":[{"apiKey":["ai:write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiLetterRequest"}}}},"responses":{"200":{"description":"Lettre rédigée","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1AiLetterResult"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Requête impossible à traiter ; Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/ai/tools/{slug}":{"post":{"operationId":"v1AiTool","summary":"Outil IA du catalogue (facturé à l’usage ; simulé avec une clé vf_test_)","tags":["B2B (v1)"],"security":[{"apiKey":["ai:write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":80},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiToolRequest"}}}},"responses":{"200":{"description":"Texte généré","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1AiToolResult"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Requête impossible à traiter ; Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/calculators/{slug}/compute":{"post":{"operationId":"v1Compute","summary":"Exécute un calculateur (valeurs par défaut complétées ; distance calculée par itinéraire et prix moyen du carburant du jour si le calculateur en a)","tags":["B2B (v1)"],"security":[{"apiKey":["catalogue:read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":80},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComputeRequest"}}}},"responses":{"200":{"description":"Résultat","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalculatorResult"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/catalogue":{"get":{"operationId":"v1GetCatalogue","summary":"Catalogue complet : catégories, lettres (fournisseurs, champs), calculateurs, outils IA, devis, tarifs","description":"Réponse mise en cache côté client : en-têtes ETag et Cache-Control ; renvoyez If-None-Match pour obtenir 304.","tags":["B2B (v1)"],"security":[{"apiKey":["catalogue:read"]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"if-none-match","in":"header"}],"responses":{"200":{"description":"Catalogue","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Catalogue"}}}},"304":{"description":"Non modifié"},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/companies":{"get":{"operationId":"v1SearchCompanies","summary":"Recherche d’entreprise dans l’annuaire SIRENE (nom, enseigne, SIREN ou SIRET)","tags":["B2B (v1)"],"security":[{"apiKey":["data:read"]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":200,"description":"Nom, enseigne, SIREN ou SIRET."},"required":true,"description":"Nom, enseigne, SIREN ou SIRET.","name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":10,"default":5},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["active","all"],"default":"active","description":"`all` : établissements fermés compris."},"required":false,"description":"`all` : établissements fermés compris.","name":"status","in":"query"}],"responses":{"200":{"description":"Entreprises","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyResults"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/companies/{siret}":{"get":{"operationId":"v1GetCompany","summary":"Fiche d’un établissement : statut, entreprise, siège social, activité, effectif, fraîcheur des données","tags":["B2B (v1)"],"security":[{"apiKey":["data:read"]}],"parameters":[{"schema":{"type":"string","pattern":"^\\d{14}$","example":"39315281200029"},"required":true,"name":"siret","in":"path"}],"responses":{"200":{"description":"Fiche entreprise","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyProfile"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/expenses/settle":{"post":{"operationId":"v1SettleExpenses","summary":"Partage de dépenses : qui doit combien à qui (soldes et remboursements en nombre minimal)","tags":["B2B (v1)"],"security":[{"apiKey":["catalogue:read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseGroup"}}}},"responses":{"200":{"description":"Répartition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Settlement"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Requête impossible à traiter ; Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/fuel/prices":{"get":{"operationId":"v1GetFuelPrices","summary":"Prix moyens du jour par carburant, en France et dans un département (prix-carburants.gouv.fr)","tags":["B2B (v1)"],"security":[{"apiKey":["data:read"]}],"parameters":[{"schema":{"type":"string","pattern":"^(\\d{2,3}|2[AB])$","description":"Département (69, 2A, 974) : ajoute ses moyennes à celles de la France."},"required":false,"description":"Département (69, 2A, 974) : ajoute ses moyennes à celles de la France.","name":"department","in":"query"}],"responses":{"200":{"description":"Prix moyens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FuelPrices"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/fuel/stations":{"get":{"operationId":"v1SearchFuelStations","summary":"Stations-service les moins chères autour d’un point ou dans une commune","tags":["B2B (v1)"],"security":[{"apiKey":["data:read"]}],"parameters":[{"schema":{"type":"string","enum":["gazole","sp95-e10","sp98","e85","gplc"],"default":"gazole"},"required":false,"name":"fuel","in":"query"},{"schema":{"type":["number","null"],"minimum":-90,"maximum":90},"required":false,"name":"lat","in":"query"},{"schema":{"type":["number","null"],"minimum":-180,"maximum":180},"required":false,"name":"lon","in":"query"},{"schema":{"type":"string","pattern":"^(\\d{5}|2[AB]\\d{3})$","description":"Code commune INSEE (Lyon : 69123). Avec `lat`/`lon` (centre), élargit autour si la commune a moins de 3 stations."},"required":false,"description":"Code commune INSEE (Lyon : 69123). Avec `lat`/`lon` (centre), élargit autour si la commune a moins de 3 stations.","name":"insee","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":30,"default":10},"required":false,"name":"radiusKm","in":"query"},{"schema":{"type":"string","enum":["price","distance"],"default":"price","description":"`price` : les moins chères d’abord, puis les plus proches."},"required":false,"description":"`price` : les moins chères d’abord, puis les plus proches.","name":"sort","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Stations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FuelStations"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/geo/addresses":{"get":{"operationId":"v1SearchAddresses","summary":"Autocomplétion et géocodage d’adresse (base adresse nationale)","tags":["B2B (v1)"],"security":[{"apiKey":["data:read"]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":200},"required":true,"name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":10,"default":5},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Adresses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResults"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/geo/cities":{"get":{"operationId":"v1SearchCities","summary":"Commune par code postal ou par nom (base adresse nationale)","description":"Un code postal à 5 chiffres renvoie toutes les communes qui le partagent. Le `label` (« 69003 Lyon ») est la valeur attendue dans le champ `commune` d’un devis ou d’un calculateur.","tags":["B2B (v1)"],"security":[{"apiKey":["data:read"]}],"parameters":[{"schema":{"type":"string","minLength":2,"maxLength":100},"required":true,"name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":20,"default":8},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Communes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CityResults"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/letters/{slug}":{"get":{"operationId":"v1GetLetter","summary":"Détail d’une lettre (champs exacts pour un fournisseur donné)","tags":["B2B (v1)"],"security":[{"apiKey":["catalogue:read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":80},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string"},"required":false,"name":"provider","in":"query"}],"responses":{"200":{"description":"Lettre","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LetterDetail"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/letters/{slug}/pdf":{"post":{"operationId":"v1LetterPdf","summary":"PDF d’une lettre complète (A4)","tags":["B2B (v1)"],"security":[{"apiKey":["letters:write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":80},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LetterRenderRequest"}}}},"responses":{"200":{"description":"Fichier PDF","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Requête impossible à traiter ; Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/letters/{slug}/render":{"post":{"operationId":"v1RenderLetter","summary":"Rendu d’une lettre : document structuré (segments avec champs à compléter), texte, champs manquants","tags":["B2B (v1)"],"security":[{"apiKey":["catalogue:read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":80},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LetterRenderRequest"}}}},"responses":{"200":{"description":"Lettre rendue","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LetterRender"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/mailings":{"post":{"operationId":"v1CreateMailing","summary":"Envoi postal d’une lettre (catalogue ou libre). Clé vf_test_ : simulé, non facturé.","tags":["B2B (v1)"],"security":[{"apiKey":["mailings:write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailingRequest"}}}},"responses":{"201":{"description":"Envoi créé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shipment"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Requête impossible à traiter ; Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Service indisponible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"v1ListMailings","summary":"Envois postaux de votre organisation, du plus récent au plus ancien (pagination par curseur)","tags":["B2B (v1)"],"security":[{"apiKey":["mailings:read"]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Nombre d’éléments par page (1 à 100, 20 par défaut)."},"required":false,"description":"Nombre d’éléments par page (1 à 100, 20 par défaut).","name":"limit","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Curseur opaque : la valeur `nextCursor` de la page précédente."},"required":false,"description":"Curseur opaque : la valeur `nextCursor` de la page précédente.","name":"cursor","in":"query"},{"schema":{"type":"string","maxLength":30,"description":"Votre référence, à l’identique."},"required":false,"description":"Votre référence, à l’identique.","name":"reference","in":"query"},{"schema":{"$ref":"#/components/schemas/ShipmentStatus"},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"Envois","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailingList"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/mailings/{id}":{"get":{"operationId":"v1GetMailing","summary":"Suivi d’un envoi postal","tags":["B2B (v1)"],"security":[{"apiKey":["mailings:read"]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Envoi","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shipment"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/mailings/{id}/proofs/{kind}":{"get":{"operationId":"v1GetMailingProof","summary":"Lien de téléchargement d’une preuve (dépôt, accusé de réception…), valable quelques minutes","tags":["B2B (v1)"],"security":[{"apiKey":["mailings:read"]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/ProofKind"},"required":true,"name":"kind","in":"path"}],"responses":{"200":{"description":"Preuve","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProofLink"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/quotes/{slug}/estimate":{"post":{"operationId":"v1EstimateQuote","summary":"Estimation d’un devis (itinéraire routier calculé si le service en a un)","tags":["B2B (v1)"],"security":[{"apiKey":["catalogue:read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":80},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteEstimateRequest"}}}},"responses":{"200":{"description":"Estimation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteEstimate"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/requests":{"post":{"operationId":"v1CreateServiceRequest","summary":"Demande un service absent du catalogue (lettre, calculateur, outil IA) pour votre organisation (gratuit)","tags":["B2B (v1)"],"security":[{"apiKey":["requests:write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceRequestInput"}}}},"responses":{"201":{"description":"Demande enregistrée","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceRequest"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"v1ListServiceRequests","summary":"Demandes de service de votre organisation et leur statut, du plus récent au plus ancien (gratuit, pagination par curseur)","tags":["B2B (v1)"],"security":[{"apiKey":["requests:read"]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Nombre d’éléments par page (1 à 100, 20 par défaut)."},"required":false,"description":"Nombre d’éléments par page (1 à 100, 20 par défaut).","name":"limit","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Curseur opaque : la valeur `nextCursor` de la page précédente."},"required":false,"description":"Curseur opaque : la valeur `nextCursor` de la page précédente.","name":"cursor","in":"query"}],"responses":{"200":{"description":"Demandes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceRequestList"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/routes":{"get":{"operationId":"v1ComputeRoutes","summary":"Itinéraire routier en voiture : distance et durée entre deux adresses ou coordonnées","tags":["B2B (v1)"],"security":[{"apiKey":["data:read"]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":300,"example":"12 rue des Lilas, 69003 Lyon","description":"Adresse (géocodée par Addok) ou « lon,lat »."},"required":true,"description":"Adresse (géocodée par Addok) ou « lon,lat ».","name":"from","in":"query"},{"schema":{"type":"string","minLength":3,"maxLength":300,"example":"2.3674,48.8656"},"required":true,"name":"to","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false","description":"`true` : ajoute le tracé simplifié de l’itinéraire (pour une carte)."},"required":false,"description":"`true` : ajoute le tracé simplifié de l’itinéraire (pour une carte).","name":"geometry","in":"query"}],"responses":{"200":{"description":"Itinéraire","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResult"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Crédits ou paiement requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Service partenaire en erreur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/search":{"get":{"operationId":"v1Search","summary":"Recherche dans le catalogue, en mots-clés ou en langage naturel","description":"Recherche hybride : mots-clés et alias (instantané) fusionnés avec une recherche sémantique (« mon propriétaire garde ma caution » → dépôt de garantie). Le sémantique n’intervient que si la requête le justifie (aucun résultat par mots-clés, ou 3 mots et plus) ; en cas d’indisponibilité, la réponse reste lexicale (`mode: lexical`).","tags":["B2B (v1)"],"security":[{"apiKey":["catalogue:read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200},"required":true,"name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":8},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["hybrid","lexical"],"default":"hybrid","description":"`lexical` : mots-clés seuls (sans appel au moteur sémantique)."},"required":false,"description":"`lexical` : mots-clés seuls (sans appel au moteur sémantique).","name":"mode","in":"query"}],"responses":{"200":{"description":"Résultats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResults"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/test/mailings/{id}/advance":{"post":{"operationId":"v1TestAdvanceMailing","summary":"Bac à sable (clé vf_test_ seulement) : fait passer un envoi de test à l’étape suivante, ou à l’étape demandée","tags":["B2B (v1)"],"security":[{"apiKey":["mailings:write"]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x20-\\x7E]{1,255}$","description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","example":"6f1c2b0e-8d4a-4f7e-9a51-3c2d1e0f9b87"},"required":false,"description":"Rend la requête rejouable sans effet en double pendant 24 h (UUID v4 recommandé). Même clé et même requête : la première réponse est renvoyée avec `Idempotent-Replayed: true`, sans nouvel envoi ni nouveau débit. Même clé pour une autre requête : 422 `idempotency_key_reused`. Requête identique encore en cours : 409 `idempotency_in_progress`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1TestAdvance"}}}},"responses":{"200":{"description":"Envoi","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shipment"}}}},"400":{"description":"Requête invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentification requise ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Accès refusé ; Accès refusé (`insufficient_scope`, `account_suspended`, `live_not_enabled`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflit ; Requête identique encore en cours (`idempotency_in_progress`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Corps trop volumineux (`payload_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Clé Idempotency-Key déjà utilisée pour une autre requête (`idempotency_key_reused`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Trop de requêtes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Erreur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"components":{"schemas":{"AddressResults":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"street":{"type":"string"},"postcode":{"type":"string"},"city":{"type":"string"},"lat":{"type":"number"},"lon":{"type":"number"}},"required":["label","street","postcode","city","lat","lon"]}}},"required":["results"],"example":{"results":[{"label":"12 Rue des Lilas 69003 Lyon","street":"12 Rue des Lilas","postcode":"69003","city":"Lyon","lat":45.7597,"lon":4.8422}]}},"AiFillRequest":{"type":"object","properties":{"letter":{"type":"string"},"provider":{"type":"string"},"text":{"type":"string","minLength":3,"maxLength":2000}},"required":["letter","text"],"example":{"letter":"resiliation-box","provider":"free","text":"Je résilie ma box Free, ligne 55443322, car je déménage le 15 novembre."}},"AiLetterRequest":{"type":"object","properties":{"text":{"type":"string","minLength":10,"maxLength":4000},"sender":{"$ref":"#/components/schemas/Sender"}},"required":["text"],"example":{"text":"Mon propriétaire ne m’a pas rendu mon dépôt de garantie deux mois après l’état des lieux de sortie.","sender":{"name":"Camille Martin","street":"12 rue des Lilas","city":"69003 Lyon"}}},"AiToolRequest":{"type":"object","properties":{"inputs":{"$ref":"#/components/schemas/Values"}},"required":["inputs"],"example":{"inputs":{"text":"Bonjour, suite à votre courrier du 12 septembre, je conteste la facture n° 4512."}}},"ApiError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"not_found"},"message":{"type":"string","example":"Cette ressource est introuvable."},"details":{}},"required":["code","message"]}},"required":["error"],"example":{"error":{"code":"insufficient_balance","message":"Solde insuffisant (1,20 € HT pour un appel à 1,90 € HT). Rechargez votre compte depuis votre espace développeur.","details":{"balanceCents":120,"priceCents":190}}}},"CalculatorResult":{"type":"object","properties":{"calculator":{"type":"string"},"values":{"$ref":"#/components/schemas/Values"},"result":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"},"unit":{"type":"string"},"caption":{"type":["string","null"]},"rows":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"]}}},"required":["label","value","unit","caption","rows"]},"route":{"type":"object","properties":{"distanceKm":{"type":"number"},"durationMin":{"type":"integer"}},"required":["distanceKm","durationMin"],"description":"Itinéraire calculé entre les deux adresses, quand la distance n’était pas fournie."},"fuelPrice":{"type":"object","properties":{"fuel":{"type":"string"},"avgCents":{"type":"number"},"updatedAt":{"type":["string","null"]}},"required":["fuel","avgCents","updatedAt"],"description":"Prix moyen du jour utilisé, quand le prix du carburant n’était pas fourni."}},"required":["calculator","values","result"],"example":{"calculator":"salaire-brut-net","values":{"amount":"3000","period":"Mensuel","status":"Non-cadre","workTime":"100","months":"12","pas":"0"},"result":{"label":"Salaire net mensuel","value":"2 340","unit":"€","caption":"avant impôt sur le revenu","rows":[{"label":"Brut horaire","value":"19,78 €"},{"label":"Brut mensuel","value":"3 000 €"}]}}},"CalculatorRoute":{"type":["object","null"],"properties":{"from":{"type":"string"},"to":{"type":"string"},"distance":{"type":"string"},"roundTrips":{"type":"string"}},"required":["from","to","distance"],"description":"Itinéraire routier (OSRM) entre les champs adresse `from` et `to`, qui remplit le champ `distance` (km, aller simple ; × 2 × `roundTrips` si ce champ est renseigné). `POST …/compute` le calcule si `distance` est absent."},"CalculatorSummary":{"type":"object","properties":{"slug":{"type":"string"},"group":{"type":"string"},"icon":{"type":"string"},"title":{"type":"string"},"short":{"type":"string"},"h1":{"type":"string"},"intro":{"type":"string"},"url":{"type":"string"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/Field"}},"presets":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"slug":{"type":"string"},"values":{"$ref":"#/components/schemas/Values"},"url":{"type":"string"}},"required":["label","slug","values","url"]}},"initialValues":{"allOf":[{"$ref":"#/components/schemas/Values"},{"description":"Valeurs initiales du jour (dates relatives résolues)."}]},"letter":{"type":["string","null"]},"route":{"$ref":"#/components/schemas/CalculatorRoute"},"fuelPrice":{"type":["object","null"],"properties":{"fuel":{"type":"string"},"price":{"type":"string"}},"required":["fuel","price"],"description":"Champ carburant et champ prix (€/L) prérempli avec le prix moyen national du jour (`GET /v1/fuel/prices`)."},"expenses":{"type":["object","null"],"properties":{"tabs":{"type":"array","items":{"type":"string"}},"example":{"$ref":"#/components/schemas/ExpenseGroup"}},"required":["tabs","example"],"description":"Mode « dépenses de groupe » (qui doit combien à qui) : onglets [calcul simple, dépenses de groupe] et exemple de départ. Calcul local et déterministe (catalogue, expenses.ts), montants en centimes."}},"required":["slug","group","icon","title","short","h1","intro","url","fields","presets","initialValues","letter","route","fuelPrice"]},"Catalogue":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"icon":{"type":"string"},"title":{"type":"string"},"short":{"type":"string"},"url":{"type":"string"}},"required":["slug","icon","title","short","url"]}},"letters":{"type":"array","items":{"$ref":"#/components/schemas/LetterSummary"}},"calculators":{"type":"array","items":{"$ref":"#/components/schemas/CalculatorSummary"}},"tools":{"type":"array","items":{"$ref":"#/components/schemas/ToolSummary"}},"quotes":{"type":"array","items":{"$ref":"#/components/schemas/QuoteSummary"}},"lookups":{"type":"array","items":{"$ref":"#/components/schemas/LookupSummary"}},"lifeEvents":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"icon":{"type":"string"},"art":{"type":"string","description":"Illustration de catégorie."},"title":{"type":"string"},"short":{"type":"string"},"h1":{"type":"string"},"intro":{"type":"string"},"url":{"type":"string"},"steps":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Identifiant stable de l’étape dans son parcours."},"title":{"type":"string"},"when":{"type":"string"},"text":{"type":"string"},"tools":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["letter","calculator","quote","tool","lookup"]},"slug":{"type":"string"}},"required":["kind","slug"]}}},"required":["key","title","text","tools"]}},"faq":{"type":"array","items":{"$ref":"#/components/schemas/Faq"}}},"required":["slug","icon","art","title","short","h1","intro","url","steps","faq"]},"description":"Événements de vie : parcours par moment de vie (étapes dans l’ordre, outils du catalogue)."},"social":{"type":"array","items":{"type":"object","properties":{"network":{"type":"string","description":"instagram, facebook, youtube ; un réseau inconnu du client est ignoré."},"label":{"type":"string"},"handle":{"type":"string"},"url":{"type":"string"},"icon":{"type":"string","description":"Tracé SVG du logo (viewBox 0 0 24 24, une couleur)."}},"required":["network","label","handle","url","icon"]},"description":"Comptes Vitef sur les réseaux sociaux."},"pricing":{"type":"object","properties":{"delivery":{"type":"array","items":{"type":"object","properties":{"mode":{"type":"string","enum":["pdf","simple","rec","ar","lre"]},"icon":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"priceCents":{"type":"integer"},"recommended":{"type":"boolean"},"channel":{"type":"string","enum":["none","postal","electronic"]},"professionalOnly":{"type":"boolean","description":"Réservé à un destinataire professionnel (LRE)."}},"required":["mode","icon","label","description","priceCents","recommended"]}}},"required":["delivery"]}},"required":["categories","letters","calculators","tools","quotes","lookups","pricing"],"example":{"categories":[{"slug":"resiliation","icon":"circle-x","title":"Résiliations","short":"Box, mobile, énergie, assurance, mutuelle, streaming, sport","url":"https://vitef.com/demarches/resiliation"}],"letters":[{"slug":"resiliation-box","category":"resiliation","icon":"wifi-off","title":"Résilier sa box internet","short":"Free, SFR, Orange, Bouygues","h1":"Lettre de résiliation box internet","badge":"Conforme loi Chatel","url":"https://vitef.com/lettres/resiliation-box","providerLabel":"Votre fournisseur","providers":[{"slug":"free","name":"Free","address":null,"url":"https://vitef.com/lettres/resiliation-box/free"}],"fields":[{"key":"ref","label":"Identifiant client","type":"text","optional":false,"placeholder":"12345678"},{"key":"recipientAddress","label":"Adresse du destinataire","type":"text","optional":false,"placeholder":"Adresse complète","autocomplete":"address"}],"signature":"optional","signatureNote":null}],"calculators":[{"slug":"salaire-brut-net","group":"Travail","icon":"euro","title":"Salaire brut en net","short":"Horaire, mensuel ou annuel, tous statuts","h1":"Salaire brut en net","intro":"Convertissez votre salaire brut en net, à l’heure, au mois ou à l’année, selon votre statut et votre temps de travail. Estimation instantanée.","url":"https://vitef.com/calculs/salaire-brut-net","fields":[{"key":"amount","label":"Salaire brut","type":"number","optional":false,"suffix":"€","default":"2500","big":true}],"presets":[{"label":"2 500 € brut en net","slug":"2500-euros-brut-en-net","values":{"amount":"2500"},"url":"https://vitef.com/calculs/salaire-brut-net/2500-euros-brut-en-net"}],"initialValues":{"amount":"2500","period":"Mensuel","status":"Non-cadre","workTime":"100","months":"12","pas":"0"},"letter":null,"route":null,"fuelPrice":null,"expenses":null}],"tools":[{"slug":"comprendre-courrier","icon":"scan-text","title":"Comprendre un courrier","short":"Impôts, CAF, huissier, banque : en clair","h1":"Comprendre un courrier administratif","intro":"Collez le texte du courrier. Vous obtenez : ce que ça veut dire, ce que vous devez faire, avant quand, et la lettre pour y répondre.","url":"https://vitef.com/outils-ia/comprendre-courrier","inputs":[{"key":"text","label":"Texte du courrier","type":"textarea","optional":false,"placeholder":"Collez ici le contenu du courrier reçu…","rows":8}]}],"quotes":[{"slug":"demenagement","icon":"truck","title":"Devis déménagement","short":"Estimation immédiate selon le volume et la distance","h1":"Devis de déménagement en ligne","intro":"Indiquez votre logement et vos adresses : le prix estimé s’affiche tout de suite, avec la distance réelle.","url":"https://vitef.com/devis/demenagement","trade":"demenageur","route":{"from":"fromAddress","to":"toAddress"},"steps":[{"title":"Votre déménagement","fields":[{"key":"fromAddress","label":"Adresse de départ","type":"text","optional":false,"placeholder":"12 rue des Lilas, 69003 Lyon","autocomplete":"address"}]}],"lead":{"offer":"devis-demenagement","phoneRule":"standard","consents":[{"recipient":"vitef","channel":"email","version":"vitef.email.2026-10-01","label":"J’accepte que Vitef me recontacte par e-mail au sujet de cette demande, pour me proposer une mise en relation.","notice":"Vitef ne transmet vos coordonnées à aucun professionnel sans votre nouvel accord, donné pour un professionnel nommé."}]}}],"lookups":[{"slug":"entreprise","icon":"building-2","title":"Vérifier une entreprise","short":"Active ou fermée, date de création, siège, effectif","h1":"Vérifier une entreprise ou un artisan","intro":"Avant de signer un devis ou de verser un acompte, vérifiez que l’entreprise existe et qu’elle est en activité.","url":"https://vitef.com/verifier/entreprise","api":{"search":"/v1/companies","detail":"/v1/companies/{siret}"}}],"lifeEvents":[{"slug":"je-demenage","icon":"truck","art":"logement","title":"Je déménage","short":"Préavis, déménageur, contrats, caution, changement d’adresse","h1":"Je déménage","intro":"Les démarches d’un déménagement, dans l’ordre où les faire.","url":"https://vitef.com/moments/je-demenage","steps":[{"key":"preavis","title":"Donner son préavis au propriétaire","when":"1 à 3 mois avant","text":"Le préavis est de 3 mois pour un logement vide, 1 mois pour un meublé ou en zone tendue (loi du 6 juillet 1989, art. 15).","tools":[{"kind":"calculator","slug":"calcul-preavis-logement"}]}],"faq":[{"q":"Quel préavis pour quitter un logement ?","a":"Trois mois pour un logement vide, un mois pour un meublé ou en zone tendue."}]}],"social":[{"network":"instagram","label":"Instagram","handle":"@vitef_app","url":"https://www.instagram.com/vitef_app/","icon":"M12 2.2c3.2 0 3.6 0 4.8.1…"}],"pricing":{"delivery":[{"mode":"pdf","icon":"download","label":"PDF à imprimer","description":"Vous imprimez, signez et postez vous-même.","channel":"none","priceCents":0,"recommended":false}]}}},"CityResults":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"postcode":{"type":"string"},"city":{"type":"string"},"label":{"type":"string"}},"required":["postcode","city","label"]}}},"required":["results"],"example":{"results":[{"postcode":"69001","city":"Lyon","label":"69001 Lyon"},{"postcode":"69003","city":"Lyon","label":"69003 Lyon"}]}},"CodeLabel":{"type":["object","null"],"properties":{"code":{"type":"string"},"label":{"type":"string"}},"required":["code","label"]},"CompanyProfile":{"type":"object","properties":{"name":{"type":"string","description":"Enseigne, à défaut dénomination."},"siret":{"type":"string"},"address":{"type":"string","description":"Adresse de l’établissement, sur une ligne.","example":"12 Rue des Ardennes, 69100 Villeurbanne"},"city":{"type":"string"},"naf":{"type":"string"},"siren":{"type":"string"},"headquarters":{"type":"boolean","description":"Établissement siège social."},"active":{"type":"boolean","description":"Établissement ouvert (SIRET actif)."},"professional":{"type":"boolean","description":"Destinataire professionnel : établissement actif d’une entreprise hors personnes publiques et associations. La lettre recommandée électronique ne requiert pas son accord préalable (art. L100 CPCE)."},"legalName":{"type":"string","description":"Dénomination de l’entreprise (unité légale) : le destinataire juridique."},"tradeName":{"type":["string","null"]},"companyActive":{"type":"boolean","description":"Entreprise en activité (non cessée)."},"legalForm":{"$ref":"#/components/schemas/CodeLabel"},"activity":{"$ref":"#/components/schemas/CodeLabel"},"foundedOn":{"type":["string","null"],"description":"Date de création de l’entreprise (AAAA-MM-JJ)."},"headcount":{"type":["string","null"],"description":"Tranche d’effectif salarié.","example":"20 à 49 salariés"},"seat":{"type":["object","null"],"properties":{"siret":{"type":"string"},"address":{"type":"string"}},"required":["siret","address"],"description":"Siège social actif : adresse des courriers juridiques à l’entreprise."},"establishments":{"type":"integer"},"dataAsOf":{"type":"object","properties":{"sourceRelease":{"type":["string","null"]},"refreshedAt":{"type":["string","null"]}},"required":["sourceRelease","refreshedAt"],"description":"Fraîcheur de l’annuaire : millésime SIRENE (INSEE) et dernier chargement."}},"required":["name","siret","address","siren","headquarters","active","professional","legalName","tradeName","companyActive","legalForm","activity","foundedOn","headcount","seat","establishments","dataAsOf"],"example":{"name":"TRANSPORTS MARTIN","siret":"39315281200029","address":"12 Rue des Ardennes, 69100 Villeurbanne","city":"Villeurbanne","naf":"49.41A","siren":"393152812","headquarters":false,"active":true,"professional":true,"legalName":"TRANSPORTS MARTIN","tradeName":null,"companyActive":true,"legalForm":{"code":"5710","label":"SAS, société par actions simplifiée"},"activity":{"code":"49.41A","label":"Transports routiers de fret interurbains"},"foundedOn":"1994-03-01","headcount":"20 à 49 salariés","seat":{"siret":"39315281200011","address":"5 Avenue Jean Jaurès, 69007 Lyon"},"establishments":2,"dataAsOf":{"sourceRelease":"2026-09-01","refreshedAt":"2026-09-14T02:37:16.000Z"}}},"CompanyResult":{"type":"object","properties":{"name":{"type":"string","description":"Enseigne, à défaut dénomination."},"siret":{"type":"string"},"address":{"type":"string","description":"Adresse de l’établissement, sur une ligne.","example":"12 Rue des Ardennes, 69100 Villeurbanne"},"city":{"type":"string"},"naf":{"type":"string"},"siren":{"type":"string"},"headquarters":{"type":"boolean","description":"Établissement siège social."},"active":{"type":"boolean","description":"Établissement ouvert (SIRET actif)."},"professional":{"type":"boolean","description":"Destinataire professionnel : établissement actif d’une entreprise hors personnes publiques et associations. La lettre recommandée électronique ne requiert pas son accord préalable (art. L100 CPCE)."}},"required":["name","siret","address","siren","headquarters","active","professional"]},"CompanyResults":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/CompanyResult"}}},"required":["results"],"example":{"results":[{"name":"TRANSPORTS MARTIN","siret":"39315281200029","address":"12 Rue des Ardennes, 69100 Villeurbanne","city":"Villeurbanne","naf":"49.41A","siren":"393152812","headquarters":false,"active":true,"professional":true},{"name":"TRANSPORTS MARTIN","siret":"39315281200011","address":"5 Avenue Jean Jaurès, 69007 Lyon","city":"Lyon","naf":"49.41A","siren":"393152812","headquarters":true,"active":true,"professional":true}]}},"ComputeRequest":{"type":"object","properties":{"values":{"$ref":"#/components/schemas/Values"},"today":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date de référence (défaut : aujourd’hui à Paris)."}},"example":{"values":{"price":"2,49","qty":"250","unit":"g","count":"1"}}},"ExpenseGroup":{"type":"object","properties":{"people":{"type":"array","items":{"type":"string","maxLength":40},"minItems":2,"maxItems":50,"description":"Participants ; désignés ensuite par leur index (0, 1, 2…).","example":["Camille","Léo","Inès"]},"expenses":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","maxLength":80},"amount":{"type":"integer","minimum":0,"maximum":100000000,"description":"Centimes."},"payer":{"type":"integer","minimum":0,"description":"Index du participant qui a payé."},"split":{"type":"object","properties":{"kind":{"type":"string","enum":["equal","exact"],"description":"`equal` : parts égales entre `among` ; `exact` : montants de `amounts`."},"among":{"type":"array","items":{"type":"integer","minimum":0},"maxItems":50,"description":"`equal` : index des participants concernés (absent ou vide : tous)."},"amounts":{"type":"array","items":{"type":"integer","minimum":0},"maxItems":50,"description":"`exact` : part de chacun en centimes, par index (0 : non concerné)."}},"default":{"kind":"equal"},"required":["kind"]}},"required":["label","amount","payer"]},"maxItems":500}},"required":["people","expenses"],"example":{"people":["Camille","Léo","Inès"],"expenses":[{"label":"Location","amount":90000,"payer":0,"split":{"kind":"equal","among":[]}},{"label":"Courses","amount":12000,"payer":1,"split":{"kind":"equal","among":[0,1]}}]}},"Faq":{"type":"object","properties":{"q":{"type":"string"},"a":{"type":"string"}},"required":["q","a"]},"Field":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["text","number","date","tel","email","textarea","radio","select","tabs"]},"optional":{"type":"boolean"},"placeholder":{"type":"string"},"hint":{"type":"string"},"suffix":{"type":"string"},"options":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"}},"required":["value"]}},"default":{"type":"string"},"rows":{"type":"integer"},"autocomplete":{"type":"string","enum":["address","company","commune"]},"big":{"type":"boolean","description":"Calculateurs : champ principal, mis en avant."},"when":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"in":{"type":"array","items":{"type":"string"}}},"required":["key","in"]},"description":"Affiché seulement si, pour chaque condition, le champ `key` (choix) vaut l’une des valeurs `in` ; un choix non touché compte pour sa première option. Masqué, le champ garde sa valeur."}},"required":["key","label","type","optional"]},"FuelPrices":{"type":"object","properties":{"asOf":{"type":"string","description":"Calcul des statistiques (ISO 8601)."},"updatedAt":{"type":["string","null"],"description":"Dernière relecture du flux prix-carburants.gouv.fr (ISO 8601)."},"source":{"type":"string","example":"prix-carburants.gouv.fr"},"maxAgeDays":{"type":"integer","description":"Seuls les prix publiés depuis moins de N jours comptent."},"national":{"type":"array","items":{"$ref":"#/components/schemas/FuelStat"}},"department":{"type":["object","null"],"properties":{"code":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/FuelStat"}}},"required":["code","items"]}},"required":["asOf","updatedAt","source","maxAgeDays","national","department"],"example":{"asOf":"2026-09-24T01:52:16.000Z","updatedAt":"2026-09-24T01:37:04.000Z","source":"prix-carburants.gouv.fr","maxAgeDays":7,"national":[{"slug":"gazole","code":"B7","label":"Gazole","count":8041,"avgCents":240.5,"medianCents":241.4,"minCents":219,"maxCents":284.9,"latestReportedAt":"2026-09-24T00:17:59.000Z"}],"department":{"code":"69","items":[{"slug":"gazole","code":"B7","label":"Gazole","count":312,"avgCents":242.9,"medianCents":241.4,"minCents":219,"maxCents":284.9,"latestReportedAt":"2026-09-24T00:17:59.000Z"}]}}},"FuelRef":{"type":"object","properties":{"slug":{"type":"string","example":"gazole"},"code":{"type":"string","description":"Code du service commun (B7, SP95_E10, SP98, E85, GPL)."},"label":{"type":"string","example":"Gazole"}},"required":["slug","code","label"]},"FuelStat":{"type":"object","properties":{"slug":{"type":"string"},"code":{"type":"string"},"label":{"type":"string"},"count":{"type":"integer","description":"Stations dont le prix compte dans la moyenne."},"avgCents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."},"medianCents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."},"minCents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."},"maxCents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."},"latestReportedAt":{"type":["string","null"]}},"required":["slug","code","label","count","avgCents","medianCents","minCents","maxCents","latestReportedAt"]},"FuelStation":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"],"description":"Nom publié, sinon l’enseigne ; `null` si inconnus."},"brand":{"type":["string","null"]},"address":{"type":"string"},"postcode":{"type":"string"},"city":{"type":"string"},"insee":{"type":["string","null"]},"department":{"type":["string","null"]},"lat":{"type":"number"},"lon":{"type":"number"},"distanceM":{"type":["number","null"],"description":"Distance au point recherché, en mètres (recherche de proximité)."},"prices":{"type":"array","items":{"type":"object","properties":{"fuel":{"type":"string"},"cents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."},"updatedAt":{"type":"string"}},"required":["fuel","cents","updatedAt"]}},"open24h":{"type":"boolean","description":"La station ne ferme jamais."},"automat24h":{"type":"boolean","description":"Pompe accessible à toute heure par carte bancaire."},"onHighway":{"type":"boolean"},"services":{"type":"array","items":{"type":"string"},"description":"LAVAGE, RESTAURATION, BOUTIQUE, DOUCHE, PARKING_PL."},"hours":{"type":["array","null"],"items":{"type":"object","properties":{"day":{"type":"integer","description":"1 = lundi … 7 = dimanche."},"closed":{"type":"boolean"},"ranges":{"type":"array","items":{"type":"string"}}},"required":["day","closed","ranges"]}}},"required":["id","name","brand","address","postcode","city","insee","department","lat","lon","distanceM","prices","open24h","automat24h","onHighway","services","hours"]},"FuelStations":{"type":"object","properties":{"fuel":{"$ref":"#/components/schemas/FuelRef"},"scope":{"type":"string","enum":["nearby","city","around"],"description":"`around` : commune avec trop peu de stations, recherche élargie autour de son centre."},"total":{"type":"integer"},"summary":{"type":["object","null"],"properties":{"count":{"type":"integer"},"avgCents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."},"medianCents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."},"minCents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."},"maxCents":{"type":"number","description":"Centimes TTC par litre (une décimale possible : 240,5)."}},"required":["count","avgCents","medianCents","minCents","maxCents"],"description":"Sur toutes les stations trouvées (100 au plus)."},"stations":{"type":"array","items":{"$ref":"#/components/schemas/FuelStation"}},"source":{"type":"string"},"maxAgeDays":{"type":"integer"}},"required":["fuel","scope","total","summary","stations","source","maxAgeDays"],"example":{"fuel":{"slug":"gazole","code":"B7","label":"Gazole"},"scope":"city","total":1,"summary":{"count":1,"avgCents":219.9,"medianCents":219.9,"minCents":219.9,"maxCents":219.9},"stations":[{"id":"69003001","name":"Intermarché","brand":"Intermarché","address":"12 Rue des Lilas","postcode":"69003","city":"Lyon","insee":"69123","department":"69","lat":45.7597,"lon":4.8422,"distanceM":null,"prices":[{"fuel":"B7","cents":219.9,"updatedAt":"2026-09-23T06:00:00.000Z"}],"open24h":false,"automat24h":true,"onHighway":false,"services":["BOUTIQUE"],"hours":[{"day":1,"closed":false,"ranges":["08:30-20:00"]},{"day":7,"closed":true,"ranges":[]}]}],"source":"prix-carburants.gouv.fr","maxAgeDays":7}},"GeoPoint":{"type":"object","properties":{"lat":{"type":"number"},"lon":{"type":"number"},"label":{"type":"string"}},"required":["lat","lon","label"]},"LetterDetail":{"type":"object","properties":{"slug":{"type":"string"},"category":{"type":"string"},"icon":{"type":"string"},"title":{"type":"string"},"short":{"type":"string"},"h1":{"type":"string"},"badge":{"type":"string"},"url":{"type":"string"},"providerLabel":{"type":["string","null"]},"providers":{"type":"array","items":{"$ref":"#/components/schemas/LetterProvider"}},"fields":{"type":"array","items":{"$ref":"#/components/schemas/Field"}},"signature":{"type":"string","enum":["optional","required","paper"],"description":"`optional` : nom imprimé, signature dessinée possible (`signatureImage`) ; `required` : signature dessinée exigée avant l’envoi ; `paper` : PDF à imprimer et signer à la main (pas d’envoi postal)."},"signatureNote":{"type":["string","null"],"description":"Explication à afficher quand la règle n’est pas `optional`."},"intro":{"type":"string"},"explain":{"type":"string"},"tip":{"type":"object","properties":{"title":{"type":"string"},"text":{"type":"string"}},"required":["title","text"]},"faq":{"type":"array","items":{"$ref":"#/components/schemas/Faq"}},"provider":{"allOf":[{"$ref":"#/components/schemas/LetterProvider"},{"type":["object","null"]}]},"senderFields":{"type":"array","items":{"$ref":"#/components/schemas/Field"}},"calculator":{"type":["string","null"]}},"required":["slug","category","icon","title","short","h1","badge","url","providerLabel","providers","fields","intro","explain","tip","faq","provider","senderFields","calculator"],"example":{"slug":"resiliation-box","category":"resiliation","icon":"wifi-off","title":"Résilier sa box internet","short":"Free, SFR, Orange, Bouygues","h1":"Lettre de résiliation box internet","badge":"Conforme loi Chatel","url":"https://vitef.com/lettres/resiliation-box","providerLabel":"Votre fournisseur","providers":[{"slug":"free","name":"Free","address":null,"url":"https://vitef.com/lettres/resiliation-box/free"}],"fields":[{"key":"ref","label":"Identifiant client","type":"text","optional":false,"placeholder":"12345678"},{"key":"recipientAddress","label":"Adresse du destinataire","type":"text","optional":false,"placeholder":"Adresse complète","autocomplete":"address"}],"signature":"optional","signatureNote":null,"intro":"Remplissez 3 champs, votre lettre de résiliation est prête. Téléchargez-la gratuitement ou laissez-nous l’envoyer en recommandé.","explain":"La résiliation prend effet au plus tard 10 jours après réception de votre demande, sauf si vous demandez une date plus tardive (article L224-39 du Code de la consommation).","tip":{"title":"Bon à savoir","text":"Rendez le matériel dans le délai prévu par votre contrat pour éviter des frais de non-restitution."},"faq":[{"q":"Combien de temps prend la résiliation ?","a":"10 jours au plus après réception de votre demande (article L224-39 du Code de la consommation)."}],"provider":null,"senderFields":[{"key":"name","label":"Prénom et nom","type":"text","optional":false,"placeholder":"Camille Martin"},{"key":"street","label":"Adresse","type":"text","optional":false,"placeholder":"12 rue des Lilas","autocomplete":"address"}],"calculator":null}},"LetterDoc":{"type":"object","properties":{"title":{"type":"string"},"sender":{"type":"array","items":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}}},"recipient":{"type":"array","items":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}}},"place":{"$ref":"#/components/schemas/Segment"},"date":{"$ref":"#/components/schemas/Segment"},"subject":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}},"body":{"type":"array","items":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}}},"signature":{"$ref":"#/components/schemas/Segment"}},"required":["title","sender","recipient","place","date","subject","body","signature"]},"LetterProvider":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"address":{"type":["array","null"],"items":{"type":"string"},"description":"Dernière adresse connue du destinataire (lignes), relevée sur sa source officielle et donnée à titre indicatif : elle a pu changer et doit être vérifiée par l’utilisateur. Sert de valeur par défaut au champ `recipientAddress`, toujours modifiable ; une valeur transmise dans `recipientAddress` la remplace."},"url":{"type":"string"}},"required":["slug","name","address","url"]},"LetterRender":{"type":"object","properties":{"letter":{"type":"string"},"provider":{"type":["string","null"]},"doc":{"$ref":"#/components/schemas/LetterDoc"},"plain":{"$ref":"#/components/schemas/PlainLetter"},"text":{"type":"string"},"missing":{"type":"array","items":{"$ref":"#/components/schemas/MissingField"}},"complete":{"type":"boolean"}},"required":["letter","provider","doc","plain","text","missing","complete"],"example":{"letter":"resiliation-box","provider":"free","doc":{"title":"Lettre de résiliation Free","sender":[[{"text":"Camille Martin","hole":false}],[{"text":"12 rue des Lilas","hole":false}],[{"text":"69003 Lyon","hole":false}]],"recipient":[[{"text":"Free","hole":false}],[{"text":"75371 Paris Cedex 08","hole":false}]],"place":{"text":"Lyon","hole":false},"date":{"text":"24 septembre 2026","hole":false},"subject":[{"text":"Résiliation de mon abonnement Free","hole":false}],"body":[[{"text":"Madame, Monsieur,","hole":false}],[{"text":"Par la présente, je vous informe de ma décision de résilier mon abonnement internet Free, identifiant client ","hole":false},{"text":"12345678","hole":false},{"text":".","hole":false}]],"signature":{"text":"Camille Martin","hole":false}},"plain":{"title":"Lettre de résiliation Free","sender":["Camille Martin","12 rue des Lilas","69003 Lyon"],"recipient":["Free","75371 Paris Cedex 08"],"place":"Lyon","date":"24 septembre 2026","subject":"Résiliation de mon abonnement Free","body":["Madame, Monsieur,","Par la présente, je vous informe de ma décision de résilier mon abonnement internet Free, identifiant client 12345678."],"signature":"Camille Martin"},"text":"Camille Martin\n12 rue des Lilas\n69003 Lyon\n\nFree\n75371 Paris Cedex 08\n\nLyon, le 24 septembre 2026\n\nObjet : Résiliation de mon abonnement Free\n\nMadame, Monsieur,\n\nPar la présente, je vous informe de ma décision de résilier mon abonnement internet Free, identifiant client 12345678.\n\nCamille Martin","missing":[],"complete":true}},"LetterRenderRequest":{"type":"object","properties":{"values":{"$ref":"#/components/schemas/Values"},"sender":{"$ref":"#/components/schemas/Sender"},"provider":{"type":"string"}},"example":{"provider":"free","values":{"ref":"55443322","motif":"Déménagement"},"sender":{"name":"Camille Martin","street":"12 rue des Lilas","city":"69003 Lyon"}}},"LetterSummary":{"type":"object","properties":{"slug":{"type":"string"},"category":{"type":"string"},"icon":{"type":"string"},"title":{"type":"string"},"short":{"type":"string"},"h1":{"type":"string"},"badge":{"type":"string"},"url":{"type":"string"},"providerLabel":{"type":["string","null"]},"providers":{"type":"array","items":{"$ref":"#/components/schemas/LetterProvider"}},"fields":{"type":"array","items":{"$ref":"#/components/schemas/Field"}},"signature":{"type":"string","enum":["optional","required","paper"],"description":"`optional` : nom imprimé, signature dessinée possible (`signatureImage`) ; `required` : signature dessinée exigée avant l’envoi ; `paper` : PDF à imprimer et signer à la main (pas d’envoi postal)."},"signatureNote":{"type":["string","null"],"description":"Explication à afficher quand la règle n’est pas `optional`."}},"required":["slug","category","icon","title","short","h1","badge","url","providerLabel","providers","fields"]},"LookupSummary":{"type":"object","properties":{"slug":{"type":"string"},"icon":{"type":"string"},"title":{"type":"string"},"short":{"type":"string"},"h1":{"type":"string"},"intro":{"type":"string"},"url":{"type":"string"},"api":{"type":"object","properties":{"search":{"type":"string"},"detail":{"type":"string"}},"required":["search","detail"],"description":"Opérations /v1 du service (recherche, puis fiche)."}},"required":["slug","icon","title","short","h1","intro","url","api"],"description":"Vérification gratuite (référentiel public), par exemple « Vérifier une entreprise »."},"MailingList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Shipment"}},"nextCursor":{"type":["string","null"],"description":"À passer dans `cursor` pour la page suivante ; null à la dernière page."},"hasMore":{"type":"boolean"}},"required":["data","nextCursor","hasMore"],"example":{"data":[{"id":"a12665a3-43e4-4b50-9593-f489ec2174cd","orderId":null,"title":"Lettre de réclamation","mode":"ar","modeLabel":"Recommandé avec AR","status":"delivered","statusLabel":"Distribuée","step":4,"lastStep":5,"trackingNumber":"1A15760000001","createdAt":"2026-09-23T10:00:00.000Z","events":[{"step":0,"status":"paid","label":"Payée","at":"2026-09-23T10:00:00.000Z"},{"step":4,"status":"delivered","label":"Distribuée","at":"2026-09-25T09:31:00.000Z"}],"recipient":["Service clients Exemple","5 avenue de la Gare","75010 Paris"],"amountCents":0,"reference":"CRM-4813","test":true,"proofs":[{"kind":"filing","label":"Preuve de dépôt"}]}],"nextCursor":"eyJ0IjoiMjAyNi0wOS0yNFQwODoxMjowMy4wMDBaIiwiaSI6IjhmMmMxZjBlIn0","hasMore":true}},"MailingRequest":{"type":"object","properties":{"letter":{"type":"string","description":"Slug de la lettre du catalogue.","example":"resiliation-box"},"provider":{"type":"string","description":"Slug du fournisseur (facultatif).","example":"free"},"values":{"$ref":"#/components/schemas/Values"},"sender":{"$ref":"#/components/schemas/Sender"},"doc":{"allOf":[{"$ref":"#/components/schemas/PlainLetter"},{"description":"Lettre libre (IA, sur mesure) : à la place de letter/values."}]},"signatureImage":{"allOf":[{"$ref":"#/components/schemas/SignatureImage"},{"description":"Signature dessinée à imprimer sur la lettre (catalogue ou lettre libre)."}]},"mode":{"$ref":"#/components/schemas/PostalMode"},"reference":{"type":"string","maxLength":30,"pattern":"^[A-Za-z0-9 _-]*$","description":"Votre référence (30 caractères, lettres, chiffres, espace, _ et -)."}},"required":["mode"],"example":{"letter":"resiliation-box","provider":"free","values":{"ref":"55443322","motif":"Déménagement"},"sender":{"name":"Camille Martin","street":"12 rue des Lilas","city":"69003 Lyon"},"mode":"ar","reference":"CRM-4812"}},"MissingField":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}},"required":["key","label"]},"PlainLetter":{"type":"object","properties":{"title":{"type":"string","maxLength":200},"sender":{"type":"array","items":{"type":"string","maxLength":200},"maxItems":8},"recipient":{"type":"array","items":{"type":"string","maxLength":200},"maxItems":8},"place":{"type":"string","maxLength":120},"date":{"type":"string","maxLength":60},"subject":{"type":"string","maxLength":300},"body":{"type":"array","items":{"type":"string","maxLength":5000},"maxItems":40},"signature":{"type":"string","maxLength":120},"signatureImage":{"$ref":"#/components/schemas/SignatureImage"}},"required":["title","sender","recipient","place","date","subject","body","signature"],"description":"Lettre entièrement textuelle (sans champ à compléter), telle qu’imprimée et envoyée."},"PostalMode":{"type":"string","enum":["simple","rec","ar"]},"ProofKind":{"type":"string","enum":["filing","delivery","return","download","rejection","negligence"]},"ProofLink":{"type":"object","properties":{"kind":{"$ref":"#/components/schemas/ProofKind"},"label":{"type":"string"},"url":{"type":"string","format":"uri","description":"Lien de téléchargement chez le prestataire, valable quelques minutes : à ouvrir aussitôt."}},"required":["kind","label","url"],"example":{"kind":"filing","label":"Preuve de dépôt","url":"https://api.vitef.com/app/sandbox/proof.pdf?kind=filing"}},"QuoteEstimate":{"type":"object","properties":{"service":{"type":"string"},"trade":{"type":"string"},"low":{"type":"number","description":"Bas de fourchette, euros TTC (historique : voir `lowCents`)."},"high":{"type":"number","description":"Haut de fourchette, euros TTC (historique : voir `highCents`)."},"lowCents":{"type":"integer","description":"Bas de fourchette en centimes TTC (préférer à `low`)."},"highCents":{"type":"integer","description":"Haut de fourchette en centimes TTC (préférer à `high`)."},"label":{"type":"string"},"caption":{"type":"string"},"rows":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"]}},"items":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"detail":{"type":"string"}},"required":["title","detail"]}},"values":{"$ref":"#/components/schemas/Values"},"distanceKm":{"type":"number"},"durationMin":{"type":"number"}},"required":["service","trade","low","high","lowCents","highCents","label","rows","items","values"],"example":{"service":"demenagement","trade":"demenageur","low":1080,"high":1610,"lowCents":108000,"highCents":161000,"label":"Prix estimé","caption":"32 m³ environ · formule standard","rows":[{"label":"Volume estimé","value":"32 m³"},{"label":"Distance","value":"465 km"}],"items":[],"values":{"home":"T3","formula":"Standard","floors":"0","heavy":"Non","storage":"Non"},"distanceKm":465,"durationMin":280}},"QuoteEstimateRequest":{"type":"object","properties":{"values":{"$ref":"#/components/schemas/Values"}},"example":{"values":{"commune":"69003 Lyon","surface":"45"}}},"QuoteLead":{"type":"object","properties":{"offer":{"type":"string","description":"Offre portée par le formulaire du devis (catalogue offers.ts)."},"phoneRule":{"type":"string","enum":["standard","enr"],"description":"`enr` : rénovation énergétique, rappel sous 5 jours ouvrés."},"consents":{"type":"array","items":{"type":"object","properties":{"recipient":{"type":"string"},"channel":{"type":"string","enum":["email","phone"]},"version":{"type":"string","description":"Version du texte de consentement (demandes de mise en relation faites sur vitef.com)."},"label":{"type":"string","description":"Libellé de la case, à afficher tel quel (jamais pré-cochée)."},"notice":{"type":"string","description":"Précision sous la case, à afficher telle quelle."}},"required":["recipient","channel","version","label","notice"]}}},"required":["offer","phoneRule","consents"],"description":"Demande de mise en relation du devis : une case par canal, textes versionnés."},"QuoteSummary":{"type":"object","properties":{"slug":{"type":"string"},"icon":{"type":"string"},"title":{"type":"string"},"short":{"type":"string"},"h1":{"type":"string"},"intro":{"type":"string"},"url":{"type":"string"},"trade":{"type":"string"},"route":{"type":["object","null"],"properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"description":"Champs adresse entre lesquels l’itinéraire est calculé."},"steps":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/Field"}}},"required":["title","fields"]}},"lead":{"$ref":"#/components/schemas/QuoteLead"}},"required":["slug","icon","title","short","h1","intro","url","trade","route","steps","lead"]},"RouteResult":{"type":"object","properties":{"distanceKm":{"type":"number"},"durationMin":{"type":"integer"},"from":{"$ref":"#/components/schemas/GeoPoint"},"to":{"$ref":"#/components/schemas/GeoPoint"},"geometry":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"Tracé simplifié : points [lon, lat] (avec `geometry=true`)."}},"required":["distanceKm","durationMin","from","to"],"example":{"distanceKm":465.3,"durationMin":281,"from":{"lat":45.7597,"lon":4.8422,"label":"12 Rue des Lilas 69003 Lyon"},"to":{"lat":48.8656,"lon":2.3674,"label":"8 Boulevard Voltaire 75011 Paris"}}},"SearchResults":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"sub":{"type":"string"},"icon":{"type":"string"},"kind":{"type":"string","example":"Lettre","description":"Lettre, Calcul, IA, Devis, Page…"},"path":{"type":"string"},"url":{"type":"string"}},"required":["title","sub","icon","kind","path","url"]}},"mode":{"type":"string","enum":["hybrid","lexical"],"description":"Moteur effectivement utilisé : `hybrid` (mots-clés + sémantique) ou `lexical` (mots-clés seuls, y compris en repli)."}},"required":["results","mode"],"example":{"results":[{"title":"Résilier sa box internet","sub":"Free, SFR, Orange, Bouygues","icon":"wifi-off","kind":"Lettre","path":"/lettres/resiliation-box","url":"https://vitef.com/lettres/resiliation-box"},{"title":"Lettre de résiliation Free","sub":"Résilier sa box internet","icon":"wifi-off","kind":"Lettre","path":"/lettres/resiliation-box/free","url":"https://vitef.com/lettres/resiliation-box/free"}],"mode":"lexical"}},"Segment":{"type":"object","properties":{"text":{"type":"string"},"hole":{"type":"boolean","description":"true : champ à compléter (text = son libellé)."}},"required":["text","hole"]},"Sender":{"type":"object","properties":{"name":{"type":"string","maxLength":120,"example":"Camille Martin"},"street":{"type":"string","maxLength":200,"example":"12 rue des Lilas"},"city":{"type":"string","maxLength":120,"example":"69003 Lyon"}},"default":{}},"ServiceRequest":{"type":"object","properties":{"id":{"type":"string"},"kind":{"$ref":"#/components/schemas/ServiceRequestKind"},"message":{"type":"string"},"query":{"type":"string"},"status":{"type":"string","enum":["new","planned","done","rejected"],"description":"new : reçue ; planned : prévue ; done : en ligne ; rejected : non retenue."},"createdAt":{"type":"string"}},"required":["id","kind","message","status","createdAt"],"example":{"id":"0287cbed-be47-4c7d-861f-a23a4445e774","kind":"calculator","message":"Un calculateur de frais de notaire pour un terrain à bâtir.","query":"frais de notaire terrain","status":"new","createdAt":"2026-09-24T08:12:03.000Z"}},"ServiceRequestInput":{"type":"object","properties":{"kind":{"$ref":"#/components/schemas/ServiceRequestKind"},"message":{"type":"string","minLength":5,"maxLength":2000,"example":"Un calculateur de frais de notaire pour un terrain à bâtir."},"query":{"type":"string","maxLength":200,"description":"Recherche d’origine, si la demande suit une recherche sans résultat."},"source":{"type":"string","maxLength":300,"description":"Page d’où vient la demande (chemin)."},"email":{"type":"string","format":"email","description":"Facultatif : prévenu quand le service est en ligne."}},"required":["message"],"example":{"kind":"calculator","message":"Un calculateur de frais de notaire pour un terrain à bâtir.","query":"frais de notaire terrain","email":"produit@agence.fr"}},"ServiceRequestKind":{"type":"string","enum":["letter","calculator","ai_tool","other"],"description":"Nature du service demandé : lettre, calculateur, outil IA ou autre."},"ServiceRequestList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ServiceRequest"}},"nextCursor":{"type":["string","null"],"description":"À passer dans `cursor` pour la page suivante ; null à la dernière page."},"hasMore":{"type":"boolean"}},"required":["data","nextCursor","hasMore"],"example":{"data":[{"id":"0287cbed-be47-4c7d-861f-a23a4445e774","kind":"calculator","message":"Un calculateur de frais de notaire pour un terrain à bâtir.","query":"frais de notaire terrain","status":"new","createdAt":"2026-09-24T08:12:03.000Z"}],"nextCursor":null,"hasMore":false}},"Settlement":{"type":"object","properties":{"total":{"type":"integer","description":"Total des dépenses, centimes."},"paid":{"type":"array","items":{"type":"integer"},"description":"Avancé par chacun (index des participants)."},"share":{"type":"array","items":{"type":"integer"},"description":"Part due par chacun."},"balance":{"type":"array","items":{"type":"integer"},"description":"Solde : positif, on lui doit ; négatif, il doit."},"transfers":{"type":"array","items":{"type":"object","properties":{"from":{"type":"integer"},"to":{"type":"integer"},"amount":{"type":"integer"}},"required":["from","to","amount"]},"description":"Remboursements, en nombre minimal."},"gaps":{"type":"array","items":{"type":"object","properties":{"expense":{"type":"integer"},"diff":{"type":"integer"}},"required":["expense","diff"]},"description":"Dépenses en montants précis dont la somme diffère du montant (écart en centimes)."}},"required":["total","paid","share","balance","transfers","gaps"],"example":{"total":102000,"paid":[90000,12000,0],"share":[36000,36000,30000],"balance":[54000,-24000,-30000],"transfers":[{"from":2,"to":0,"amount":30000},{"from":1,"to":0,"amount":24000}],"gaps":[]}},"Shipment":{"type":"object","properties":{"title":{"type":"string"},"mode":{"$ref":"#/components/schemas/ShipmentMode"},"modeLabel":{"type":"string"},"status":{"$ref":"#/components/schemas/ShipmentStatus"},"statusLabel":{"type":"string"},"step":{"type":"integer"},"lastStep":{"type":"integer","description":"4 (simple, recommandé) ou 5 (recommandé avec AR)."},"trackingNumber":{"type":"string"},"createdAt":{"type":"string"},"events":{"type":"array","items":{"$ref":"#/components/schemas/ShipmentEvent"}},"id":{"type":"string"},"orderId":{"type":["string","null"]},"recipient":{"type":"array","items":{"type":"string"}},"recipientEmail":{"type":"string","description":"LRE : adresse e-mail du destinataire."},"amountCents":{"type":"integer"},"reference":{"type":["string","null"]},"test":{"type":"boolean","description":"Envoi simulé (clé vf_test_) : rien n’est posté."},"proofs":{"type":"array","items":{"type":"object","properties":{"kind":{"$ref":"#/components/schemas/ProofKind"},"label":{"type":"string"}},"required":["kind","label"]},"description":"Preuves disponibles (dépôt, accusé de réception…), à télécharger via …/proofs/{kind}."},"contentProof":{"type":"object","properties":{"label":{"type":"string"},"sha256":{"type":"string","description":"Empreinte SHA-256 du document exact remis à l’impression."},"url":{"type":"string","format":"uri","description":"Lien signé et durable vers l’attestation PDF."}},"required":["label","sha256","url"],"description":"Recommandé papier (hors API B2B) : preuve de contenu, une fois la lettre remise à La Poste. Gardée 5 ans."},"document":{"$ref":"#/components/schemas/PlainLetter"}},"required":["title","mode","modeLabel","status","statusLabel","step","lastStep","createdAt","events","id","orderId","recipient","amountCents","reference","test","proofs"],"example":{"id":"8f2c1f0e-5b7a-4c1e-9a3d-2f6b8e1c4d20","orderId":null,"title":"Résiliation Free","mode":"ar","modeLabel":"Recommandé avec AR","status":"posted","statusLabel":"Remise à La Poste","step":2,"lastStep":5,"trackingNumber":"1A12345678901","createdAt":"2026-09-24T08:12:03.000Z","events":[{"step":0,"status":"paid","label":"Payée","at":"2026-09-24T08:12:03.000Z"},{"step":1,"status":"printed","label":"Imprimée","at":"2026-09-24T09:40:00.000Z"},{"step":2,"status":"posted","label":"Remise à La Poste","at":"2026-09-24T15:02:00.000Z"}],"recipient":["Free – Service Résiliation","TSA 20001","75371 Paris Cedex 08"],"amountCents":940,"reference":"CRM-4812","test":false,"proofs":[{"kind":"filing","label":"Preuve de dépôt"}]}},"ShipmentEvent":{"type":"object","properties":{"step":{"type":"integer","description":"0 payée, 1 imprimée, 2 remise à La Poste, 3 acheminement, 4 distribuée, 5 AR signé."},"status":{"$ref":"#/components/schemas/ShipmentStatus"},"label":{"type":"string"},"at":{"type":"string"}},"required":["step","status","label","at"]},"ShipmentMode":{"type":"string","enum":["simple","rec","ar","lre"]},"ShipmentStatus":{"type":"string","enum":["paid","printed","posted","in_transit","delivered","ar_signed","returned","error","canceled"]},"SignatureImage":{"type":"string","maxLength":200000,"description":"Signature dessinée, en data URL PNG (fond transparent conseillé, 200 k caractères au plus). Imprimée au-dessus du nom.","example":"data:image/png;base64,iVBORw0KGgo…"},"ToolSummary":{"type":"object","properties":{"slug":{"type":"string"},"icon":{"type":"string"},"title":{"type":"string"},"short":{"type":"string"},"h1":{"type":"string"},"intro":{"type":"string"},"url":{"type":"string"},"inputs":{"type":"array","items":{"$ref":"#/components/schemas/Field"}}},"required":["slug","icon","title","short","h1","intro","url","inputs"]},"V1AiFillResult":{"type":"object","properties":{"values":{"$ref":"#/components/schemas/Values"},"filled":{"type":"integer"}},"required":["values","filled"],"example":{"values":{"ref":"55443322","motif":"Déménagement","date":"15 novembre 2026"},"filled":3}},"V1AiLetterResult":{"type":"object","properties":{"title":{"type":"string"},"recipient":{"type":"array","items":{"type":"string"}},"subject":{"type":"string"},"body":{"type":"array","items":{"type":"string"}},"tip":{"type":"string"},"doc":{"$ref":"#/components/schemas/PlainLetter"}},"required":["title","recipient","subject","body","tip","doc"],"example":{"title":"Demande de restitution du dépôt de garantie","recipient":["Monsieur le propriétaire","8 boulevard Voltaire","75011 Paris"],"subject":"Restitution de mon dépôt de garantie","body":["Madame, Monsieur,","L’état des lieux de sortie a été établi le 15 juillet 2026, sans réserve. Plus de deux mois après la remise des clés, mon dépôt de garantie ne m’a pas été restitué.","Conformément à l’article 22 de la loi du 6 juillet 1989, je vous demande de me le restituer sous huit jours.","Je vous prie d’agréer, Madame, Monsieur, l’expression de mes salutations distinguées."],"tip":"Envoyez cette lettre en recommandé avec accusé de réception : elle fait courir les intérêts de retard.","doc":{"title":"Demande de restitution du dépôt de garantie","sender":["Camille Martin","12 rue des Lilas","69003 Lyon"],"recipient":["Monsieur le propriétaire","8 boulevard Voltaire","75011 Paris"],"place":"Lyon","date":"24 septembre 2026","subject":"Restitution de mon dépôt de garantie","body":["Madame, Monsieur,","L’état des lieux de sortie a été établi le 15 juillet 2026, sans réserve. Plus de deux mois après la remise des clés, mon dépôt de garantie ne m’a pas été restitué.","Conformément à l’article 22 de la loi du 6 juillet 1989, je vous demande de me le restituer sous huit jours.","Je vous prie d’agréer, Madame, Monsieur, l’expression de mes salutations distinguées."],"signature":"Camille Martin"}}},"V1AiToolResult":{"type":"object","properties":{"slug":{"type":"string"},"text":{"type":"string"}},"required":["slug","text"],"example":{"slug":"corriger-texte","text":"Bonjour, suite à votre courrier du 12 septembre, je conteste la facture n° 4512."}},"V1TestAdvance":{"type":"object","properties":{"to":{"type":"string","enum":["printed","posted","in_transit","delivered","ar_signed","returned","error"]}},"example":{"to":"delivered"}},"Values":{"type":"object","additionalProperties":{"type":"string","maxLength":5000},"description":"Valeurs du formulaire, par clé de champ."}},"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Clé d’API Vitef : `vf_live_…` (production) ou `vf_test_…` (simulation)."}}}}