Aller au contenu
AtlasVialo
Développeurs

Un moteur de capacité dans votre TMS.

Une seule API REST pour tout ce que fait Vialo Fleet : chiffrer un chargement en plus sur un trajet, synchroniser vos tournées, réserver du fret et être prévenu de chaque changement. JSON en entrée et en sortie, montants en centimes.

Base URL  https://fleet.atlasvialo.com/api/v1

Démarrage rapide

  1. 1Créez une clé

    Dans Vialo Fleet, ouvrez Intégrations et créez une clé API. Elle n’est affichée qu’une fois.

  2. 2Demandez un verdict

    Envoyez un trajet et quelques envois à POST /evaluate. Rien n’est enregistré.

  3. 3Synchronisez vos tournées

    Envoyez chaque tournée de votre TMS avec PUT et sa propre référence, puis lisez les suggestions.

  4. 4Écoutez

    Ajoutez un endpoint webhook pour être prévenu des réservations, enlèvements et livraisons.

curl -X POST https://fleet.atlasvialo.com/api/v1/evaluate \
  -H "Authorization: Bearer vk_…" \
  -H "Content-Type: application/json" \
  -d @evaluate.json

Authentification

Envoyez la clé comme jeton Bearer ou dans X-Api-Key. Une clé agit pour une entreprise avec les droits du propriétaire qui l’a créée, et cesse de fonctionner dès qu’elle est révoquée.

Chaque écriture sauf /evaluate prend un en-tête Idempotency-Key : une nouvelle tentative ne réserve jamais deux fois.

Authorization: Bearer vk_1a2b3c4d_…
X-Api-Key: vk_1a2b3c4d_…
Idempotency-Key: 6f1e2c8a-…

Évaluer un envoi

Le moteur à la demande : cet envoi en plus est-il bon pour ce véhicule sur ce trajet ?

POST/evaluate

Jusqu’à 100 envois par appel. Chaque réponse contient le verdict, les six contrôles, tout le calcul, la place de l’envoi parmi vos arrêts et chaque heure d’arrivée. Un prix null renvoie le prix le plus bas qui respecte vos règles.

Requête
{
  "currency": "EUR",
  "vehicle": {
    "max_weight_kg": 2000,
    "cost_per_km_minor": 80,
    "cost_per_hour_minor": 4000
  },
  "route": {
    "origin": {
      "lat": 62.3908,
      "lng": 17.3069
    },
    "destination": {
      "lat": 63.8258,
      "lng": 20.263
    },
    "via": [
      {
        "point": {
          "lat": 62.487,
          "lng": 17.326
        },
        "label": "Timrå delivery",
        "service_time_s": 900,
        "load_change": {
          "weight_kg": -1200
        }
      }
    ],
    "depart_from": "2026-10-05T07:00:00+02:00",
    "onboard": {
      "weight_kg": 1500
    }
  },
  "rules": {
    "max_delay_s": 7200,
    "min_profit_minor": 2000
  },
  "loads": [
    {
      "ref": "ORDER-4711",
      "pickup": {
        "lat": 62.6323,
        "lng": 17.9379
      },
      "dropoff": {
        "lat": 63.2909,
        "lng": 18.7153
      },
      "weight_kg": 300,
      "pickup_from": "2026-10-05T08:00:00+02:00",
      "pickup_until": "2026-10-05T14:00:00+02:00",
      "deliver_by": "2026-10-05T18:00:00+02:00",
      "price_minor": 40000
    }
  ]
}
Réponse
{
  "results": [
    {
      "ref": "ORDER-4711",
      "verdict": "good",
      "blocked_by": null,
      "arithmetic": {
        "detour_distance_m": 8700,
        "detour_duration_s": 2220,
        "extra_cost_minor": 4560,
        "price_minor": 40000,
        "profit_minor": 35440,
        "profit_per_hour_minor": 57470,
        "min_price_minor": 6560,
        "currency": "EUR"
      },
      "insertion": {
        "pickup_after": 1,
        "dropoff_after": 1
      },
      "depart_at": "2026-10-05T05:00:00.000Z",
      "pickup_eta": "2026-10-05T06:12:40.000Z",
      "gates": [
        {
          "gate": "physical",
          "outcome": "pass",
          "detail": {
            "peak_kg": 600,
            "max_kg": 2000
          }
        },
        "…"
      ],
      "stops": [
        {
          "sequence": 0,
          "kind": "origin",
          "eta": "…",
          "load_after_kg": 1500
        },
        "…"
      ]
    }
  ],
  "route": {
    "base_distance_m": 276000,
    "base_duration_s": 11400,
    "via_stops": 1
  }
}

Connecteur TMS

Vos tournées et véhicules, avec vos propres références.

PUT/tms/vehicles/{ref}

Créez ou mettez à jour un véhicule par votre référence : capacité, coût par kilomètre, coût par heure et équipement.

Requête
{
  "label": "Truck 07",
  "max_weight_kg": 24000,
  "cost_per_km_minor": 172,
  "cost_per_hour_minor": 4800,
  "tags": [
    "tail-lift"
  ]
}
Réponse
{
  "id": "9c1e…",
  "external_ref": "TRUCK-07",
  "created": true
}
PUT/tms/tours/{ref}

Créez une tournée avec ses arrêts, ses variations de charge et ses échéances. La renvoyer la remplace tant que rien n’est réservé.

Requête
{
  "vehicle_ref": "TRUCK-07",
  "origin": {
    "point": {
      "lat": 62.3908,
      "lng": 17.3069
    },
    "label": "Sundsvall depot"
  },
  "destination": {
    "point": {
      "lat": 63.8258,
      "lng": 20.263
    },
    "label": "Umeå depot"
  },
  "depart_from": "2026-10-05T07:00:00+02:00",
  "onboard": {
    "weight_kg": 1500
  },
  "stops": [
    {
      "point": {
        "lat": 62.487,
        "lng": 17.326
      },
      "label": "Customer A",
      "service_time_s": 900,
      "load_change": {
        "weight_kg": -1000
      },
      "latest_arrival": "2026-10-05T10:00:00+02:00"
    }
  ]
}
Réponse
{
  "trip_id": "4f2a…",
  "external_ref": "TOUR/2026-10-05/17",
  "replaced": null,
  "base_distance_m": 276000,
  "base_duration_s": 11400
}
GET/tms/tours/{ref}/suggestions

Le fret qui convient à la tournée maintenant, meilleur profit par heure en premier, avec la probabilité que votre équipe l’accepte.

Réponse
{
  "trip_id": "4f2a…",
  "external_ref": "TOUR/2026-10-05/17",
  "suggestions": [
    {
      "offer_id": "b71d…",
      "package_id": "0e9c…",
      "pickup_label": "Härnösand",
      "dropoff_label": "Örnsköldsvik",
      "weight_kg": 300,
      "price_minor": 40000,
      "min_price_minor": 6560,
      "profit_minor": 35440,
      "profit_per_hour_minor": 57470,
      "detour_duration_s": 2220,
      "currency": "EUR",
      "acceptance_likelihood": 0.82,
      "insertion": {
        "pickup_after": 1,
        "dropoff_after": 1
      },
      "expires_at": "…"
    }
  ]
}
DELETE/tms/tours/{ref}

Annulez une tournée sans réservation.

Réponse
{
  "cancelled": true,
  "trip_id": "4f2a…"
}

Offres et réservation

Lisez les offres classées d’un trajet, réservez-en une ou proposez votre prix.

GET/trips/{id}/offers

Les offres classées d’un trajet, plus les envois bloqués par une règle et la raison.

Réponse
{
  "offers": [
    {
      "id": "b71d…",
      "package_id": "0e9c…",
      "reward_minor": 40000,
      "profit_minor": 35440,
      "profit_per_hour_minor": 57470,
      "acceptance_likelihood": 0.82,
      "…": "…"
    }
  ],
  "rejects": [
    {
      "package_id": "77aa…",
      "blocked_by": "sla",
      "…": "…"
    }
  ]
}
POST/offers/{id}/accept

Réservez une offre. Chaque contrôle est refait sur le plan actuel ; un envoi ne peut être réservé qu’une seule fois.

Requête
{
  "confirm_tracking": true
}
Réponse
{
  "accepted": true,
  "assignment_id": "a3d0…",
  "trip_id": "4f2a…",
  "package_id": "0e9c…",
  "agreed_price_minor": 40000
}
POST/offers/{id}/quote

Proposez votre propre prix sur une offre. En dessous de vos règles, il est refusé avant envoi.

Requête
{
  "price_minor": 42000,
  "message": "We pass Härnösand around 08:15.",
  "confirm_tracking": true
}
Réponse
{
  "conversation_id": "c19f…",
  "quote_id": "q2b8…",
  "profit_minor": 37440,
  "min_quote_minor": 6560
}

Références externes

Retrouvez tout véhicule, trajet ou envoi par l’identifiant que votre système utilise déjà.

GET/{vehicles|trips|packages}/by-ref/{ref}

Retrouvez l’identifiant AtlasVialo derrière votre référence. Encodez la référence dans l’URL.

Réponse
{
  "id": "4f2a…",
  "external_ref": "TOUR/2026-10-05/17"
}

Webhooks

Des événements signés poussés vers votre serveur, renvoyés jusqu’à leur arrivée.

POST/webhooks

Ajoutez un endpoint HTTPS, éventuellement pour certains événements seulement. La réponse contient le secret de signature.

Requête
{
  "url": "https://tms.example.com/atlasvialo",
  "events": [
    "booking.created",
    "trip.offers_updated"
  ]
}
Réponse
{
  "id": "w81c…",
  "url": "https://tms.example.com/atlasvialo",
  "events": [
    "booking.created",
    "trip.offers_updated"
  ],
  "secret": "whsec_…",
  "active": true
}
POST/webhooks/{id}/test

Envoyez tout de suite un événement de test signé et voyez la réponse de votre endpoint.

Réponse
{
  "delivered": true,
  "status": 200,
  "error": null
}
GET/webhooks/{id}/deliveries

Les dernières livraisons avec leur statut, le nombre de tentatives et la dernière erreur.

Réponse
{
  "deliveries": [
    {
      "id": "d5e2…",
      "event": "booking.created",
      "status": "delivered",
      "attempts": 1,
      "last_status": 200,
      "created_at": "…"
    }
  ]
}

Indicateurs et apprentissage

L’entonnoir des trajets aux réservations et ce qui bloque le fret.

GET/metrics/funnel?from=…&to=…

Trajets publiés, trajets avec offres, envois évalués, possibles, réservés et livrés, chiffre d’affaires et profit net.

Réponse
{
  "trips_posted": 42,
  "trips_with_offers": 37,
  "candidates_evaluated": 1180,
  "viable_offers": 214,
  "bookings": 61,
  "delivered": 58,
  "booked_revenue_minor": 1830000,
  "booked_profit_minor": 1412000,
  "rates": {
    "trips_with_offers": 0.881,
    "viable_of_evaluated": 0.181,
    "booked_of_viable": 0.285
  }
}
GET/metrics/insights

Les contrôles qui bloquent le plus de fret, et combien d’envois bloqués une règle plus souple laisserait passer.

Réponse
{
  "blocked": [
    {
      "blocked_by": "sla",
      "reason": "delay_exceeds_max",
      "n": 312
    },
    {
      "blocked_by": "margin",
      "reason": "profit_below_min",
      "n": 140
    }
  ],
  "what_if": [
    {
      "rule": "max_delay_s",
      "change": "+25%",
      "would_pass": 64
    }
  ]
}

Vérifier un webhook

X-Vialo-Signature vaut t=<secondes unix>,v1=<HMAC-SHA256 hexadécimal de « t.corps brut » avec le secret de votre endpoint>. Recalculez-le, comparez en temps constant et refusez les horodatages anciens. Utilisez le champ id pour ignorer les doublons.

POST https://tms.example.com/atlasvialo
{
  "id": "d5e2…",
  "event": "booking.created",
  "created_at": "2026-10-05T06:01:12.000Z",
  "data": { "trip_id": "4f2a…", "trip_external_ref": "TOUR/2026-10-05/17",
            "package_id": "0e9c…", "agreed_price_minor": 40000, "currency": "EUR" }
}
Node.js
const [t, v1] = header.split(',').map((p) => p.split('=')[1]);
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
const ok = crypto.timingSafeEqual(Buffer.from(v1, 'hex'), expected)
  && Math.abs(Date.now() / 1000 - Number(t)) < 300;

Erreurs

Les erreurs sont en JSON avec un code : 400 requête invalide (avec le détail), 401 clé absente ou révoquée, 403, 404, 409 pour les conflits comme external_ref_exists ou tour_has_bookings, et 422 quand un trajet ne peut pas être calculé.

{
  "error": "tour_has_bookings",
  "trip_id": "4f2a…"
}

Les distances et temps routiers viennent de notre propre calculateur d’itinéraires. Il couvre aujourd’hui la Suède ; les envois en dehors sont répondus comme non calculables.