vtcOS

Documentation développeur

Intégrez l'estimateur tarifaire et le système de réservation vtcOS sur votre site en quelques minutes. Deux options : le widget JS (le plus simple) ou l'API REST (contrôle total).

Widget JS

Shadow DOM, 6 ko gzippé, aucune dépendance, thème personnalisable. À privilégier pour une intégration rapide.

API REST

JSON sur HTTPS, idempotence, rate limit clair. À privilégier si vous construisez votre propre UX.

Widget — Quickstart

Ajoutez un <div> cible, puis le script du widget :

<div id="vtc-widget"></div>

<script
  src="https://vtcos.upradar.cloud/widget.js"
  data-api-key="vtc_pk_live_XXXXXXXXXXX"
  data-target="#vtc-widget"></script>

C'est tout. Le widget s'affiche, charge vos véhicules et vos tarifs, gère l'autocomplétion d'adresse Google Maps et l'estimation en temps réel.

Une clé publique live (vtc_pk_live_…) est obligatoire. Utilisez vtc_pk_test_… pour les tests (n'entame pas les crédits).

Attributs du widget

AttributDéfautDescription
data-api-keyObligatoire. Clé publique vtc_pk_live_… ou vtc_pk_test_….
data-api-urlhttps://app.vtcos.upradar.cloud/apiURL de l'API (à ne changer qu'en self-hosting).
data-targetSélecteur CSS où injecter le widget (ex. #vtc-widget).
data-themedarklight ou dark.
data-primary-color#508ff8Couleur principale (CTA, accents).
data-font-family'Inter', sans-serifPolice à utiliser.
data-border-radius16pxRayon des angles.
data-logo-urlURL du logo affiché en haut.
data-restrict-countryfrCode pays pour l'autocomplétion (ex. fr, be).
data-show-breakdowntrueAfficher le détail du prix (prise en charge, km, min…).
data-show-powered-bytrueAfficher « Propulsé par vtcOS ».
data-enable-bookingtrueBouton « Réserver » après estimation.
data-cta-typenoneCTA complémentaire : link, tel, webhook, none.
data-cta-valueValeur du CTA (URL, numéro, endpoint webhook).
data-cta-labelRéserverLibellé du bouton CTA.
data-langfrLangue de l'UI.

Événements JS du widget

Le widget émet des événements DOM personnalisés que vous pouvez intercepter pour analytics ou automation :

const vtc = document.querySelector('vtc-calculator-widget');

vtc.addEventListener('vtc:estimate', (e) => {
  console.log('Estimation reçue', e.détail);
  // e.détail = { price, route, vehicle_id, ... }
});

vtc.addEventListener('vtc:booking_submitted', (e) => {
  // Tracking conversion GA4 / Meta Pixel
  dataLayer.push({ event: 'vtc_booking', email: e.détail.email });
});

vtc.addEventListener('vtc:cta_click', (e) => {
  // Bouton CTA cliqué
});
ÉvénementDétails
vtc:estimateEstimateResult (prix, route, options, vehicle_id, is_test).
vtc:booking_submitted{ email, name } — après envoi de la demande de réservation.
vtc:cta_clickDernière estimation — déclenché au clic sur le bouton CTA configuré.

Thème & couleurs

Le widget utilise un Shadow DOM : ses styles sont isolés du reste de votre site. Vous customisez via les attributs data-* sans risque de conflit CSS.

<script
  src="https://vtcos.upradar.cloud/widget.js"
  data-api-key="vtc_pk_live_XXX"
  data-target="#vtc-widget"
  data-theme="dark"
  data-primary-color="#e6c364"
  data-font-family="'Playfair Display', serif"
  data-border-radius="12px"
  data-logo-url="https://monsite.com/logo.png"></script>

CSP & CORS

Si votre site utilise une Content Security Policy stricte, autorisez :

Content-Security-Policy:
  script-src 'self' https://vtcos.upradar.cloud;
  connect-src 'self' https://app.vtcos.upradar.cloud https://maps.googleapis.com;
  img-src 'self' data: https://*;
  font-src 'self' https://fonts.gstatic.com;
  style-src 'self' 'unsafe-inline';

Le CORS de l'API vtcOS est ouvert (origin *) sur les endpoints publics protégés par clé API. Les clés publiques limitent l'accès au seul domaine que vous avez déclaré dans Paramètres → Clés API → Domaines autorisés.

API REST — URL de base

https://app.vtcos.upradar.cloud/api/v1

Toutes les réponses sont en JSON, encodage UTF-8. HTTPS obligatoire.

Authentification

Deux types de clés :

  • Clé publique (vtc_pk_live_…) : utilisable depuis le navigateur, restreinte aux domaines autorisés.
  • Clé secrète (vtc_sk_live_…) : uniquement côté serveur, ne jamais exposer.

Passez la clé dans l'en-tête Authorization :

Authorization: Bearer vtc_pk_live_XXXXXXXXXXXXXXX

Alternative : en-tête X-API-Key, ou paramètre ?api_key=… pour les webhooks.

POST /v1/estimate

Calcule le prix d'une course. Consomme un crédit (sauf clés _test_).

Requête

POST /v1/estimate HTTP/1.1
Host: app.vtcos.upradar.cloud/api
Authorization: Bearer vtc_pk_live_XXX
Content-Type: application/json

{
  "origin": { "address": "15 Avenue des Champs-Élysées, Paris" },
  "destination": { "address": "Aéroport Charles-de-Gaulle, Roissy" },
  "departure_datetime": "2026-05-17T08:30:00",
  "vehicle_id": "uuid-du-vehicule",
  "options": ["child_seat"]
}

Origine et destination acceptent soit address (string), soit lat/lng (nombres).

Réponse

{
  "request_id": "c3f5a1e2-...",
  "price": {
    "amount_ht": 85.50,
    "currency": "EUR",
    "détails": { "baseFare": 5, "distanceCost": 36.5, "timeCost": 24, ... }
  },
  "route": {
    "distance_km": 24.3,
    "duration_min": 45,
    "origin": { "lat": 48.8698, "lng": 2.3076 },
    "destination": { "lat": 49.0097, "lng": 2.5479 }
  },
  "vehicle_id": "uuid-du-vehicule",
  "departure_datetime": "2026-05-17T08:30:00",
  "options": ["child_seat"],
  "is_test": false
}

En-tête de réponse : X-Request-ID (identifiant unique de la requête).

GET /v1/vehicles

Liste les véhicules actifs du compte (pour affichage dans votre UI).

{
  "vehicles": [
    {
      "id": "uuid",
      "brand": "Mercedes",
      "model": "Classe E",
      "version": "AMG",
      "color": "Noir",
      "registration": "AB-123-CD",
      "photoUrls": ["https://..."],
      "sortOrder": 1
    }
  ]
}

GET /v1/places/*

Proxy Google Maps — pas de clé à exposer dans votre frontend.

Autocomplete

GET /v1/places/autocomplete?query=paris&country=fr

// Réponse
{ "predictions": [{ "description": "Paris, France", "place_id": "..." }] }

Reverse geocode

GET /v1/places/reverse-geocode?lat=48.8566&lng=2.3522

// Réponse
{ "address": "Rue de Rivoli, 75001 Paris, France" }

POST /v1/booking/submit

Soumet une demande de réservation (statut provisoire). Déclenche :

  • Un email au VTC avec lien vers la demande.
  • Un email de confirmation au client avec mention « statut provisoire ».
POST /v1/booking/submit
Authorization: Bearer vtc_pk_live_XXX
Content-Type: application/json

{
  "pickupDate": "2026-05-18T10:00:00",
  "pickupAddress": "15 Avenue des Champs-Élysées, Paris",
  "dropoffAddress": "Aéroport Charles-de-Gaulle",
  "clientName": "Jean Dupont",
  "clientEmail": "jean@example.com",
  "clientPhone": "+33612345678",
  "vehicleId": "uuid-optionnel",
  "estimatePrice": 85.50,
  "message": "2 passagers + 3 bagages",
  "options": ["child_seat"]
}

La réservation est créée en statut RECEIVED. Le VTC la valide depuis son dashboard ; le client reçoit ensuite un email de confirmation ou de refus.

GET /v1/usage

Retourne l'état des crédits et des paliers de tarification. Clé secrète requise.

{
  "balanceHt": 24.30,
  "monthlyEstimates": 47,
  "monthlyTotalHt": 14.10,
  "activeTier": "T1",
  "tierPriceHt": 0.30,
  "tiers": [
    { "name": "T1", "from": 0, "to": 100, "priceHt": 0.30, "active": true },
    ...
  ]
}

POST /v1/webhook/cta

Le widget peut déclencher un webhook vers votre système quand le client clique le CTA, via l'attribut data-cta-type="webhook". vtcOS relaye côté serveur pour ne pas exposer votre endpoint aux bloqueurs CORS.

POST /v1/webhook/cta
Authorization: Bearer vtc_pk_live_XXX

{
  "url": "https://votreserveur.com/réservation",
  "data": { // le résultat de l'estimation entier  }
}

Réponse : 202 Accepted immédiat. vtcOS POSTe votre URL en arrière-plan avec le corps data.

Gestion des erreurs

Les erreurs suivent un format uniforme :

{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Solde epuise. Rechargez votre compte.",
    "request_id": "c3f5a1e2-..."
  }
}
Code HTTPCodeSens
400VALIDATION_ERRORDonnées de requête invalides.
401UNAUTHORIZEDClé API manquante ou révoquée.
402INSUFFICIENT_CREDITSSolde insuffisant. Rechargez le compte.
403FORBIDDEN_DOMAINDomaine non autorisé pour cette clé publique.
403SECRET_KEY_REQUIREDEndpoint réservé aux clés secrètes.
429RATE_LIMITTrop de requêtes, ralentissez.
500INTERNAL_ERRORErreur serveur, réessayer plus tard.

Rate limits

  • /v1/estimate : 60 requêtes / minute / clé.
  • /v1/booking/submit : 10 demandes / heure / IP.
  • /v1/places/* : 120 requêtes / minute / clé.

En cas de dépassement : HTTP 429 + en-tête Retry-After indiquant le délai en secondes.

Changelog

  • 2026-04-17 — Ajout data-enable-booking, endpoint /v1/places/reverse-geocode, flow réservation provisoire.
  • 2026-04-15 — Tarifs par véhicule, options configurables, majorations (nuit/dimanche/férié).
  • 2026-04-10 — Premier release public du widget et de l'API v1.