Guide API v1

SATF CONGO FLEET API

API Fleet v1

Passerelle SaaS multi-client entre vos systèmes et Wialon.

Base URL: localhost:8000/api/v1 (variable .env, défaut localhost:8000)

Version: v1 (préfixe URL)


Authentification

Chaque client reçoit un token API propre à la plateforme. Le token Wialon interne n’est jamais exposé.

Authorization: Bearer {votre_token_api}
Accept: application/json

Gestion des tokens

  • Les tokens sont stockés en base sous forme de hash SHA-256.
  • Un token peut avoir une date d’expiration (expires_at).
  • Des abilities peuvent restreindre les permissions (["*"] = accès complet).
  • Abilities disponibles : fleet:read, fleet:reports, fleet:webhooks.
  • Le token Wialon (WIALON_TOKEN) reste côté serveur uniquement.
Ability Endpoints
fleet:read Véhicules, positions, groupes, historique, capteurs, événements, modèles de rapports
fleet:reports Exécution et suivi de rapports async (/reports/*, /groups/{group}/reports)
fleet:webhooks Gestion des webhooks
* Accès complet

Erreurs d’authentification

Code Message
401 Unauthenticated. — header Authorization absent
401 Invalid API token. — token inconnu
401 API token has expired.
403 Client account is inactive.

Rate limiting

Limite par client : rate_limit_per_minute (défaut 60 req/min).

En cas de dépassement : HTTP 429 Too Many Requests.

Header de réponse Laravel standard : X-RateLimit-Limit, X-RateLimit-Remaining.


Endpoints

Véhicules

GET /vehicles

Liste les véhicules du client connecté.

Query params :

  • active_only (bool, défaut true)
curl -H "Authorization: Bearer {token}" \
  https://example.com/api/v1/vehicles

Réponse :

{
  "data": [
    {
      "id": 1,
      "name": "Camion 01",
      "plate_number": "AB-123-CD",
      "imei": "123456789012345",
      "is_active": true,
      "last_position_at": "2026-05-29T10:15:00+00:00",
      "metadata": {}
    }
  ]
}

GET /vehicles/{vehicle}

Détail d’un véhicule appartenant au client.


Positions

GET /vehicles/{vehicle}/position

Dernière position connue (cache local synchronisé depuis Wialon).

{
  "data": {
    "vehicle_id": 1,
    "latitude": 48.8566,
    "longitude": 2.3522,
    "speed": 45.5,
    "course": 180,
    "altitude": 35,
    "satellites": 12,
    "gps_time": "2026-05-29T10:14:00+00:00",
    "received_at": "2026-05-29T10:14:05+00:00"
  }
}

GET /vehicles/positions

Dernières positions de tous les véhicules actifs du client.


Groupes

GET /groups

Groupes Wialon mappés au client.

GET /groups/{group}/vehicles

Véhicules d’un groupe.


Modèles de rapports

Les modèles (templates) Wialon accessibles au client sont ceux affectés à ses groupes dans le backoffice (Paramètres → Rapports ou fiche groupe Wialon). Même principe d’isolation que pour les véhicules : un template non associé au client renvoie 404.

Ability requise : fleet:read

GET /report-templates

Liste tous les templates disponibles pour le client, avec les groupes auxquels chacun est rattaché.

Query params :

Param Description
since ISO 8601 — sync incrémentale (templates ou bindings modifiés depuis cette date)
include wialon_data — inclut le payload JSON Wialon complet (volumineux)
curl -H "Authorization: Bearer {token}" \
  "https://example.com/api/v1/report-templates?since=2026-06-01T00:00:00Z"

Réponse :

{
  "data": [
    {
      "id": 3,
      "name": "Fuel template",
      "purpose": "fuel",
      "wialon_template_id": 2,
      "template_type": "avl_unit",
      "requires_unit": true,
      "parameters": "…",
      "checksum": "abc123",
      "tables_count": 1,
      "synced_at": "2026-05-29T10:00:00+00:00",
      "updated_at": "2026-05-29T10:00:00+00:00",
      "resource": {
        "wialon_resource_id": 23045518,
        "name": "Fuel resource"
      },
      "groups": [
        {
          "id": 1,
          "name": "Fleet A",
          "wialon_group_id": 20837054,
          "report_purpose": "fuel",
          "is_default": true
        }
      ]
    }
  ],
  "meta": {
    "catalog_synced_at": "2026-05-29T10:00:00+00:00",
    "since": null,
    "count": 1
  }
}

GET /report-templates/{template}

Détail d’un template par son ID local (wialon_report_templates.id). Paramètre include=wialon_data supporté.

GET /groups/{group}/report-templates

Templates affectés à un groupe Wialon du client (format orienté affectation).

Query params : since, include=wialon_data

Réponse (extrait) :

{
  "data": [
    {
      "binding_id": 12,
      "report_purpose": "fuel",
      "is_default": true,
      "template": {
        "id": 3,
        "name": "Fuel template",
        "wialon_template_id": 2,
        "requires_unit": true,
        "resource": {
          "wialon_resource_id": 23045518,
          "name": "Fuel resource"
        }
      }
    }
  ],
  "meta": {
    "group_id": 1,
    "group_name": "Fleet A",
    "wialon_group_id": 20837054,
    "catalog_synced_at": "2026-05-29T10:00:00+00:00",
    "count": 1
  }
}

Workflow recommandé côté client

  1. GET /report-templates (ou sync incrémentale avec since)
  2. Stocker localement id (gateway), wialon_template_id, resource.wialon_resource_id, requires_unit
  3. Option A (recommandée) — IDs gateway locaux dans POST /reports/execute/gateway
  4. Option B — IDs Wialon bruts dans POST /reports/execute
Concept ID gateway (local) ID Wialon
Groupe groups[].id groups[].wialon_group_id
Template report-templates[].id wialon_template_id + resource.wialon_resource_id
Véhicule vehicles[].id vehicles[].wialon_unit_id

Historique

GET /vehicles/{vehicle}/history?from=&to=

Positions historiques en cache local.

Param Requis Description
from oui ISO 8601 ou Y-m-d H:i:s
to oui ISO 8601 ou Y-m-d H:i:s

Intervalle max : 31 jours (configurable via WIALON_HISTORY_MAX_INTERVAL_DAYS).


GET /vehicles/{vehicle}/sensors

Capteurs synchronisés depuis Wialon (sync planifiée ou manuelle).

{
  "data": [
    {
      "id": 1,
      "vehicle_id": 1,
      "wialon_sensor_id": 42,
      "name": "Fuel level",
      "type": "fuel",
      "value": "75",
      "unit": "%",
      "measured_at": "2026-05-29T10:14:00+00:00"
    }
  ]
}

Trajets & carburant

Les rapports Wialon utilisent un resource ID et un template ID propres à chaque ressource Wialon. La plateforme les synchronise localement et les résout automatiquement par groupe véhicule.

Résolution du template

Ordre de priorité pour trips, fuel et general :

  1. report_template_id (optionnel) — ID local du catalogue (wialon_report_templates.id)
  2. Affectation par groupe Wialon — configurée dans le backoffice (Paramètres → Rapports)
  3. Template tagué — premier template du catalogue avec le purpose correspondant
  4. Fallback .envWIALON_{TYPE}_REPORT_RESOURCE_ID / WIALON_{TYPE}_REPORT_TEMPLATE_ID

Synchronisation du catalogue (admin)

  • Backoffice : Paramètres → Rapports → « Synchroniser depuis Wialon »
  • CLI : php artisan wialon:sync-reports (--dry-run pour prévisualiser)

Après sync, taguer chaque template (trips, fuel, general) et affecter les templates par groupe Wialon.

GET /vehicles/{vehicle}/trips?from=&to=

Query params optionnels :

Param Description
report_template_id ID local du template catalogue (priorité maximale)

GET /vehicles/{vehicle}/fuel?from=&to=

Mêmes paramètres que /trips. Données issues du rapport Wialon résolu pour le véhicule.

Réponse type :

{
  "vehicle_id": 1,
  "from": "2026-05-01T00:00:00+00:00",
  "to": "2026-05-29T23:59:59+00:00",
  "data": []
}

Événements

GET /events

Query params optionnels : vehicle_id, from, to, per_page (défaut 50).


Rapports asynchrones

Ability requise : fleet:reports

GET /reports

Liste paginée des rapports déjà générés pour le client.

Query params : group_id, status, report_template_id, from, to, per_page (défaut 30).

GET /groups/{group}/reports

Rapports stockés pour un groupe Wialon.

POST /groups/{group}/reports

Génère un rapport pour un groupe (ID mapping local dans l'URL). Le corps utilise les IDs Wialon du template :

{
  "wialon_resource_id": 23045518,
  "wialon_template_id": 2,
  "from": "2026-05-01T00:00:00Z",
  "to": "2026-05-29T23:59:59Z",
  "format": "json",
  "label": "Fuel May 2026",
  "wialon_unit_id": 12345678
}

wialon_unit_id est requis si le template a requires_unit: true.

POST /groups/{group}/reports/gateway

Même objectif que ci-dessus, avec les IDs gateway locaux. Le groupe est déjà dans l'URL (wialon_group_mappings.id).

{
  "gateway_template_id": 3,
  "from": "2026-05-01T00:00:00Z",
  "to": "2026-05-29T23:59:59Z",
  "format": "json",
  "label": "Fuel May 2026",
  "gateway_vehicle_id": 42
}

gateway_vehicle_id est requis si le template a requires_unit: true.

POST /reports/execute

Lance un rapport asynchrone avec les identifiants Wialon (recommandé) :

{
  "wialon_group_id": 20837054,
  "wialon_resource_id": 23045518,
  "wialon_template_id": 2,
  "from": "2026-05-01T00:00:00Z",
  "to": "2026-05-29T23:59:59Z",
  "format": "json",
  "label": "Fuel May 2026"
}

Pour un template unité (requires_unit: true) :

{
  "wialon_group_id": 20837054,
  "wialon_resource_id": 23045518,
  "wialon_template_id": 2,
  "wialon_unit_id": 12345678,
  "from": "2026-05-01T00:00:00Z",
  "to": "2026-05-29T23:59:59Z"
}
Champ Requis Description
wialon_group_id oui ID groupe Wialon (groups[].wialon_group_id)
wialon_resource_id oui ID ressource Wialon du template
wialon_template_id oui ID template Wialon dans la ressource
from / to oui Période ISO 8601
wialon_unit_id si template unité ID unité Wialon dans le groupe
format non json, pdf, csv (défaut json)
label non Libellé libre

Mode legacy — résolution automatique par type :

{
  "type": "trips",
  "wialon_unit_id": 12345678,
  "from": "2026-05-01T00:00:00Z",
  "to": "2026-05-29T23:59:59Z",
  "format": "json"
}

Types legacy : trips, fuel, general. Le template est résolu via le groupe du véhicule, puis le catalogue tagué, puis .env.

POST /reports/execute/gateway

Lance un rapport asynchrone avec les IDs gateway (locaux à la plateforme). La résolution Wialon est faite côté serveur.

{
  "gateway_group_id": 1,
  "gateway_template_id": 3,
  "from": "2026-05-01T00:00:00Z",
  "to": "2026-05-29T23:59:59Z",
  "format": "json",
  "label": "Fuel May 2026"
}

Pour un template unité (requires_unit: true) :

{
  "gateway_group_id": 1,
  "gateway_template_id": 3,
  "gateway_vehicle_id": 42,
  "from": "2026-05-01T00:00:00Z",
  "to": "2026-05-29T23:59:59Z"
}
Champ Requis Description
gateway_group_id oui ID mapping groupe (GET /groupsid)
gateway_template_id oui ID template catalogue (GET /report-templatesid)
from / to oui Période ISO 8601
gateway_vehicle_id si template unité ID véhicule local (GET /vehiclesid)
format non json, pdf, csv (défaut json)
label non Libellé libre

Réponse 202 Accepted — inclut les IDs Wialon résolus dans meta.resolved_wialon :

{
  "data": {
    "id": 12,
    "report_type": "fuel",
    "status": "pending",
    "group_id": 1,
    "report_template_id": 3,
    "from": "...",
    "to": "...",
    "format": "json"
  },
  "meta": {
    "resolved_wialon": {
      "wialon_group_id": 20837054,
      "wialon_resource_id": 23045518,
      "wialon_template_id": 2,
      "wialon_unit_id": null
    }
  }
}

Les endpoints gateway (/reports/execute/gateway, /groups/{group}/reports/gateway) renvoient meta.resolved_wialon. Les endpoints Wialon bruts renvoient uniquement data.

Réponse 202 Accepted (mode Wialon ou legacy) :

{
  "data": {
    "id": 12,
    "report_type": "trips",
    "status": "pending",
    "vehicle_id": 1,
    "from": "...",
    "to": "...",
    "format": "json"
  }
}

GET /reports/{reportJob}

Statut : pending, running, completed, failed. Inclut result lorsque le rapport est terminé.

GET /reports/{reportJob}/wialon-responses

Liste les archives JSON brutes Wialon liées au job (appels API, payloads).

GET /reports/{reportJob}/wialon-responses/{archive}

Contenu décodé d'une archive Wialon (archive + payload).


Webhooks

GET /webhooks

POST /webhooks

{
  "url": "https://client.example.com/webhooks/fleet",
  "events": ["vehicle.position.updated", "vehicle.event.created"]
}

Réponse 201 — le champ secret n’est retourné qu’à la création.

DELETE /webhooks/{webhookEndpoint}


Signature HMAC des webhooks

Chaque livraison inclut :

Header Description
X-Satf-Signature HMAC-SHA256 du body JSON brut
X-Satf-Event Type d’événement
X-Satf-Delivery-Id ID de livraison

Vérification côté client :

$expected = hash_hmac('sha256', $request->getContent(), $secret);
if (! hash_equals($expected, $request->header('X-Satf-Signature'))) {
    abort(401);
}

Les échecs sont retentés automatiquement (max 5 tentatives, intervalle 5 min).


Erreurs courantes

Code Cas
404 Ressource inexistante ou n’appartenant pas au client
422 Validation (intervalle trop long, paramètres manquants)
429 Rate limit dépassé
502 Erreur Wialon interne

Format :

{
  "message": "Description lisible",
  "errors": {}
}

Synchronisation & cache

Jobs planifiés (Scheduler Laravel + cron) :

Job Fréquence
SyncWialonUnitsJob toutes les 10 min
SyncWialonPositionsJob toutes les 1 min
SyncWialonSensorsJob toutes les 15 min
SyncWialonVehicleHistoryJob toutes les heures
RetryFailedWebhooksJob toutes les 5 min

Cron serveur :

* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1

Versionnement

  • Version actuelle : v1 (préfixe /api/v1)
  • Les breaking changes futurs seront publiés sous /api/v2
  • v1 restera supportée pendant une période de transition annoncée

Sécurité

  • Token Wialon : variable d’environnement serveur uniquement
  • Tokens clients : hash SHA-256, rotation possible via création d’un nouveau token
  • Isolation stricte par client_id sur véhicules, positions, événements, modèles de rapports, rapports et webhooks
  • Journalisation API (api_request_logs) : client, endpoint, méthode, durée, statut HTTP