Guide de démarrage de l'API

Cette page sert de guide rapide pour les intégrateurs backend, mobile et web. Elle liste les étapes métier dans le bon ordre, les endpoints à appeler, le payload minimal et une réponse minimale représentative pour chaque endpoint clé.

Vue d'ensemble
Principe

Le superadmin prépare l'offre, puis le client se connecte, recherche et consulte le détail.

Attention
Point critique

Un départ n'apparaît en recherche que si la chaîne complète est active et cohérente.

Vue générale

Cette vue regroupe les repères rapides utiles avant d'entrer dans les étapes du flow. Les providers SMS ci-dessous sont déjà disponibles pour les parcours OTP et peuvent être choisis explicitement côté intégration cliente.

Provider SMS 1 — EasySend

Provider principal déjà intégré avec deux modes d'appel distincts selon le besoin opérationnel ou les tests d'intégration.

  • sms_provider : easysend
  • sms_mode : rest ou http
  • Usage : OTP sur téléphone
  • Choix : utilisable directement depuis Swagger ou les apps clientes

Provider SMS 2 — TopMessage

Provider alternatif déjà intégré pour permettre un fallback applicatif côté mobile, desktop ou backend quand EasySend n'est pas retenu.

  • sms_provider : topmessage
  • Mode : provider alternatif prêt à l'emploi
  • Usage : OTP sur téléphone
  • But : fallback explicite ou choix manuel depuis Swagger / intégrateurs
1

Connexion superadmin

Obtenir le bearer token qui servira à préparer toute l'offre transport.
Ce token devra être envoyé dans l'en-tête Authorization: Bearer ... sur tous les endpoints d'administration suivants.

Public
POST /api/auth/login Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
identifier string body oui Email ou telephone du superadmin.
password string body oui Mot de passe du superadmin.
Payload minimal
{
  "identifier": "superadmin@ticketnet.ci",
  "password": "SuperAdmin123!"
}
Reponse minimale
{
  "success": true,
  "message": "Connexion reussie",
  "data": {
    "access_token": "...",
    "refresh_token": "...",
    "user": {
      "id": "user-id",
      "photo_url": "https://cdn.ticketnet.ci/users/superadmin.jpg"
    },
    "roles": ["superadmin"],
    "permissions": ["companies.create"]
  }
}
2

Créer une ville

Créer ou vérifier les destinations métier normalisées.

Bearer superadmin
POST /api/locations Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
name string body oui Nom de la localisation.
type string body oui Type de localisation, par exemple city.
country string body non Pays de rattachement.
Payload minimal
{
  "name": "Abidjan",
  "type": "city",
  "country": "Cote d'Ivoire"
}
Reponse minimale
{
  "success": true,
  "message": "Localisation creee",
  "data": {
    "id": "location-id-abidjan",
    "name": "Abidjan",
    "type": "city"
  }
}
3

Créer une compagnie

Enregistrer le transporteur qui proposera les trajets.

Bearer superadmin
POST /api/companies Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
name string body oui Nom de la compagnie.
phone string body non Telephone principal de la compagnie.
email string body non Email principal de la compagnie.
city string body non Ville descriptive de la compagnie.
country string body non Pays de la compagnie.
Payload minimal
{
  "name": "UTB",
  "phone": "0701020304",
  "email": "contact@utb.ci",
  "city": "Abidjan",
  "country": "Cote d'Ivoire"
}
Reponse minimale
{
  "success": true,
  "message": "Compagnie creee",
  "data": {
    "id": "company-id-utb",
    "name": "UTB",
    "status": "active"
  }
}
4

Créer une gare physique

Représenter le lieu physique réel, partagé ou dédié.
Une gare physique peut être partagée par plusieurs compagnies ou n'être utilisée que par une seule.

Bearer superadmin
POST /api/transport-hubs Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
location_id uuid body oui ID de la ville ou localisation parente.
name string body oui Nom de la gare physique.
address string body non Adresse textuelle de la gare.
photo_url string body non Image illustrative de la gare.
lat number body oui Latitude de la gare.
lng number body oui Longitude de la gare.
status string body non Statut de la gare.
Payload minimal
{
  "location_id": "location-id-abidjan",
  "name": "Gare d'Adjame",
  "address": "Adjame, face a la mairie",
  "photo_url": "https://cdn.ticketnet.ci/hubs/adjame.jpg",
  "lat": 5.3599517,
  "lng": -4.0082563,
  "status": "active"
}
Reponse minimale
{
  "success": true,
  "message": "Gare transport creee",
  "data": {
    "id": "transport-hub-id-adjame",
    "name": "Gare d'Adjame",
    "location": {
      "id": "location-id-abidjan",
      "name": "Abidjan"
    }
  }
}
5

Rattacher la compagnie à une gare

Créer la présence opérationnelle de la compagnie dans la gare.
C'est ce niveau qui permet de dire quelle compagnie opère dans quelle gare, avec son point d'embarquement, son contact local ou son libellé d'affichage.

Bearer superadmin
POST /api/company-hubs Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
company_id uuid body oui ID de la compagnie.
transport_hub_id uuid body oui ID de la gare physique.
display_name string body oui Nom affiché côté client.
internal_location string body non Quai, zone ou point d'embarquement interne.
phone string body non Telephone local.
email string body non Email local.
status string body non Statut de la presence compagnie.
Payload minimal
{
  "company_id": "company-id-utb",
  "transport_hub_id": "transport-hub-id-adjame",
  "display_name": "UTB - Adjame",
  "internal_location": "Quai 2 - Zone nord",
  "phone": "0102030405",
  "email": "adjame@utb.ci",
  "status": "active"
}
Reponse minimale
{
  "success": true,
  "message": "Presence compagnie creee",
  "data": {
    "id": "company-hub-id-utb-adjame",
    "display_name": "UTB - Adjame",
    "company": {
      "id": "company-id-utb",
      "name": "UTB"
    }
  }
}
6

Créer un trajet

Définir la liaison théorique entre ville de départ et destination.
Le trajet décrit la relation commerciale entre deux villes. Il ne correspond pas encore à un départ daté.

Bearer superadmin
POST /api/trips Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
company_id uuid body oui ID de la compagnie.
origin_location_id uuid body oui ID de la ville de depart.
destination_location_id uuid body oui ID de la ville d'arrivee.
name string body non Libelle du trajet.
code string body non Code interne du trajet.
Payload minimal
{
  "company_id": "company-id-utb",
  "origin_location_id": "location-id-abidjan",
  "destination_location_id": "location-id-bouake",
  "name": "Abidjan - Bouake",
  "code": "ABJ-BKE",
  "status": "active"
}
Reponse minimale
{
  "success": true,
  "message": "Trajet cree",
  "data": {
    "id": "trip-id-abj-bke",
    "name": "Abidjan - Bouake",
    "status": "active"
  }
}
7

Créer un départ réel

Rendre une offre visible et vendable pour la recherche client.
Un départ ne pourra remonter dans la recherche que s'il est actif, cohérent avec le trajet et rattaché à des gares compagnie valides.

Bearer superadmin
POST /api/trip-departures Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
trip_id uuid body oui ID du trajet.
origin_company_hub_id uuid body oui ID du point de depart exploite par la compagnie.
destination_company_hub_id uuid body oui ID du point d'arrivee exploite par la compagnie.
departure_at datetime ISO 8601 body oui Date et heure de depart.
arrival_estimated_at datetime ISO 8601 body non Date et heure d'arrivee estimee.
price int body oui Prix du ticket en entier.
capacity_total int body non Capacite totale.
capacity_remaining int body non Places restantes.
vehicle_label string body non Libelle du vehicule.
Payload minimal
{
  "trip_id": "trip-id-abj-bke",
  "origin_company_hub_id": "company-hub-id-utb-adjame",
  "destination_company_hub_id": "company-hub-id-utb-bouake-centre",
  "departure_at": "2026-03-20T14:30:00.000Z",
  "arrival_estimated_at": "2026-03-20T18:45:00.000Z",
  "vehicle_label": "Bus VVIP",
  "price": 4000,
  "capacity_total": 70,
  "capacity_remaining": 22,
  "stopovers_label": "Direct (sans escale)",
  "status": "active"
}
Reponse minimale
{
  "success": true,
  "message": "Depart cree",
  "data": {
    "id": "departure-id-abj-bke-1430",
    "price": 4000,
    "capacity_remaining": 22,
    "status": "active"
  }
}
8

Inscription client

Créer un compte client avec email ou téléphone puis passer à la vérification OTP.
Utiliser ce flow quand l'utilisateur n'existe pas encore dans le système.

Public
POST /api/auth/register Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
email string body conditionnel Email du client. Requis si phone est absent.
phone string body conditionnel Telephone du client. Requis si email est absent.
sms_provider string body conditionnel Provider SMS a utiliser si un telephone est envoye.
sms_mode string body conditionnel Mode rest ou http pour EasySend si sms_provider vaut easysend.
Payload minimal
{
  "phone": "0701020304",
  "sms_provider": "topmessage"
}
Reponse minimale
{
  "success": true,
  "message": "Inscription reussie",
  "data": {
    "userId": "client-id",
    "next_step": "verify_otp"
  }
}
9

Demander un OTP

Renvoyer un OTP pour un identifiant déjà connu dans le système.
Utiliser ce flow quand le compte existe déjà et qu'il faut renvoyer un code sans recréer l'utilisateur.

Public
POST /api/auth/request-otp Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
identifier string body oui Email ou telephone existant.
sms_provider string body conditionnel Provider SMS a utiliser si identifier est un numero de telephone.
sms_mode string body conditionnel Mode rest ou http pour EasySend si sms_provider vaut easysend.
Payload minimal
{
  "identifier": "0701020304",
  "sms_provider": "topmessage"
}
Reponse minimale
{
  "success": true,
  "message": "OTP envoye",
  "data": {
    "otp_expires_in": 300
  }
}
10

Vérifier un OTP

Valider l'OTP et connecter immédiatement le client.
La réponse retourne directement la session complète : access token, refresh token, user, rôles et permissions.

Public
POST /api/auth/verify-otp Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
identifier string body oui Email ou telephone a verifier.
otp string body oui Code OTP a 6 chiffres.
Payload minimal
{
  "identifier": "0701020304",
  "otp": "123456"
}
Reponse minimale
{
  "success": true,
  "message": "OTP verifie",
  "data": {
    "access_token": "...",
    "refresh_token": "...",
    "user": {
      "id": "client-id",
      "photo_url": "https://cdn.ticketnet.ci/users/client-01.jpg"
    },
    "roles": ["client"],
    "permissions": [],
    "password_changed": false
  }
}
11

Demander un OTP de réinitialisation

Déclencher un OTP de réinitialisation par email ou téléphone.
Utiliser ce flow quand l'utilisateur a oublié son mot de passe et doit être reconnecté après validation du code.

Public
POST /api/auth/forgot-password Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
identifier string body oui Email ou telephone du compte a reinitialiser.
sms_provider string body conditionnel Provider SMS a utiliser si identifier est un numero de telephone.
sms_mode string body conditionnel Mode rest ou http pour EasySend si sms_provider vaut easysend.
Payload minimal
{
  "identifier": "client@ticketnet.com"
}
Reponse minimale
{
  "success": true,
  "message": "OTP de reinitialisation envoye",
  "data": {
    "otp_expires_in": 300
  }
}
12

Vérifier l'OTP de réinitialisation

Valider l'OTP de réinitialisation et reconnecter l'utilisateur.
La réponse retourne immédiatement une nouvelle session utilisable côté mobile, web ou desktop.

Public
POST /api/auth/verify-forgot-otp Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
identifier string body oui Email ou telephone a verifier.
otp string body oui Code OTP a 6 chiffres.
Payload minimal
{
  "identifier": "client@ticketnet.com",
  "otp": "123456"
}
Reponse minimale
{
  "success": true,
  "message": "OTP de reinitialisation verifie",
  "data": {
    "access_token": "...",
    "refresh_token": "...",
    "user": {
      "id": "client-id",
      "photo_url": "https://cdn.ticketnet.ci/users/client-01.jpg"
    },
    "roles": ["client"],
    "permissions": [],
    "password_changed": false
  }
}
13

Connexion client

Le client se connecte avant toute recherche ou consultation détaillée.
À partir de cette étape, toutes les requêtes métier côté client doivent envoyer un bearer token valide.

Public
POST /api/auth/login Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
identifier string body oui Email ou telephone du client.
password string body oui Mot de passe actuel du client.
Payload minimal
{
  "identifier": "0701020304",
  "password": "123456"
}
Reponse minimale
{
  "success": true,
  "message": "Connexion reussie",
  "data": {
    "access_token": "...",
    "refresh_token": "...",
    "user": {
      "id": "client-id",
      "photo_url": "https://cdn.ticketnet.ci/users/client-01.jpg"
    },
    "roles": ["client"],
    "permissions": [],
    "password_changed": true
  }
}
14

Rafraîchir le token

Échanger un refresh token valide contre une nouvelle session.
Utiliser ce flow quand l'access token a expiré mais que la session utilisateur doit rester ouverte.

Public
POST /api/auth/refresh-token Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
refresh_token string body oui Refresh token valide retourne lors du login ou de la verification OTP.
Payload minimal
{
  "refresh_token": "REFRESH_TOKEN"
}
Reponse minimale
{
  "success": true,
  "message": "Token rafraichi",
  "data": {
    "access_token": "...",
    "refresh_token": "...",
    "user": {
      "id": "client-id"
    },
    "roles": ["client"],
    "permissions": [],
    "password_changed": true
  }
}
15

Déconnexion client

Invalider le refresh token courant pour fermer proprement la session.
Après cette étape, le refresh token ne doit plus être réutilisé par l'application cliente.

Bearer client
POST /api/auth/logout Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
Authorization string header oui Bearer token du client connecte.
refresh_token string body oui Refresh token a invalider.
Payload minimal
{
  "refresh_token": "REFRESH_TOKEN"
}
Reponse minimale
{
  "success": true,
  "message": "Deconnexion reussie",
  "data": {
    "success": true
    }
}
16

Consulter mon profil

Récupérer les informations du compte actuellement connecté.
Utiliser cet endpoint au démarrage de l'application cliente pour hydrater le profil et l'état de session.

Bearer client
GET /api/auth/me Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
Authorization string header oui Bearer token du client connecte.
Payload minimal

Aucun body requis. Utiliser les query params ou l'identifiant dans l'URL.

Reponse minimale
{
  "success": true,
  "message": "Profil recupere",
  "data": {
    "id": "client-id",
    "email": "client@ticketnet.com",
    "phone": "0701020304",
    "photo_url": "https://cdn.ticketnet.ci/users/client-01.jpg",
    "status": "active",
    "roles": ["client"]
  }
}
17

Mettre à jour mon profil

Mettre à jour les informations personnelles après connexion.
Les données complémentaires du client sont renseignées ici, pas au moment du register initial.

Bearer client
PUT /api/auth/me Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
Authorization string header oui Bearer token du client connecte.
first_name string body non Prenom du client.
last_name string body non Nom du client.
date_of_birth date body non Date de naissance.
gender string body non Sexe du client.
residence string body non Lieu d'habitation.
city string body non Ville de residence.
country string body non Pays de residence.
photo_url string body non URL de la photo de profil du client.
Payload minimal
{
  "first_name": "Awa",
  "last_name": "Traore",
  "date_of_birth": "1998-05-12",
  "gender": "female",
  "residence": "Cocody Riviera",
  "city": "Abidjan",
  "country": "Cote d'Ivoire",
  "photo_url": "https://cdn.ticketnet.ci/users/awa-traore.jpg"
}
Reponse minimale
{
  "success": true,
  "message": "Profil mis a jour",
  "data": {
    "id": "client-id",
    "first_name": "Awa",
    "last_name": "Traore",
    "photo_url": "https://cdn.ticketnet.ci/users/awa-traore.jpg",
    "city": "Abidjan",
    "country": "Cote d'Ivoire"
  }
}
18

Changer mon mot de passe

Permettre au client de remplacer son mot de passe actuel ou l'OTP utilisé comme mot de passe par défaut.
À utiliser après connexion, notamment quand l'application invite l'utilisateur à personnaliser son mot de passe.

Bearer client
POST /api/auth/change-password Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
Authorization string header oui Bearer token du client connecte.
current_password string body oui Mot de passe actuel du client.
new_password string body oui Nouveau mot de passe souhaite.
Payload minimal
{
  "current_password": "123456",
  "new_password": "MonNouveauMotDePasse123!"
}
Reponse minimale
{
  "success": true,
  "message": "Mot de passe modifie",
  "data": {
    "success": true
  }
}
19

Lister les destinations client

Alimenter une recherche assistée et forcer la sélection d'une ville normalisée.
Sans le query parameter search, l'endpoint retourne la liste paginée de toutes les villes actives.

Bearer client
GET /api/locations/active?search=bou&page=1&limit=10 Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
Authorization string header oui Bearer token du client connecte.
search string query non Texte saisi par le client pour filtrer les villes.
page int query non Numero de page.
limit int query non Nombre maximum de villes a retourner.
Payload minimal

Aucun body requis. Utiliser les query params ou l'identifiant dans l'URL.

Reponse minimale
{
  "success": true,
  "message": "Villes disponibles recuperees",
  "data": {
    "data": [
      {
        "id": "location-id-bouake",
        "name": "Bouake",
        "type": "city"
      }
    ],
    "meta": {
      "total": 1,
      "per_page": 10,
      "last_page": 1
    }
  }
}
20

Lister les filtres officiels

Récupérer les valeurs backend officielles pour horaires, prix, tri et paliers de rayon.
Ces données servent à alimenter les filtres de recherche de départ afin de garantir que les valeurs envoyées au backend soient conformes.
Le front doit utiliser uniquement les rayons autorisés renvoyés par le backend : 10, 20, 30, 40, 50 et 60 km.

Bearer client
GET /api/trip-departures/search-filters Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
Authorization string header oui Bearer token du client connecte.
Payload minimal

Aucun body requis. Utiliser les query params ou l'identifiant dans l'URL.

Reponse minimale
{
  "success": true,
  "message": "Filtres de recherche recuperes",
  "data": {
    "time_slots": ["morning", "afternoon", "evening"],
    "price_ranges": ["economic", "medium", "premium"],
    "sort_options": ["nearest", "earliest", "cheapest", "fastest"],
    "radius_steps_km": [10, 20, 30, 40, 50, 60]
  }
}
21

Rechercher les départs

Chercher les départs dans un rayon autorisé autour du client pour une destination donnée.
La recherche doit commencer à 10 km. Si aucun résultat n'est trouvé, le front doit demander confirmation au client avant de relancer la recherche avec le palier suivant : 20, puis 30, jusqu'à 60 km maximum.
Les champs comme time_slots, price_ranges, company_ids et sort ne sont pas obligatoires pour une recherche simple.

Bearer client
POST /api/trip-departures/search Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
Authorization string header oui Bearer token du client connecte.
destination_location_id uuid body oui ID de la destination choisie.
lat number body oui Latitude actuelle du client.
lng number body oui Longitude actuelle du client.
travel_date date body oui Date de voyage souhaitee.
radius_km int body non Rayon maximal autorise en kilometres. Valeurs permises : 10, 20, 30, 40, 50, 60.
time_slots string[] body non Tranches horaires officielles du backend.
price_ranges string[] body non Gammes de prix officielles du backend.
company_ids uuid[] body non Liste des compagnies a filtrer.
sort string body non Critere de tri officiel du backend.
page int body non Numero de page.
limit int body non Nombre maximum de departs a retourner.
Payload minimal
{
  "destination_location_id": "location-id-bouake",
  "lat": 5.348,
  "lng": -4.027,
  "travel_date": "2026-03-20",
  "radius_km": 10,
  "time_slots": ["morning"],
  "price_ranges": ["economic", "medium"],
  "company_ids": ["company-id-utb"],
  "sort": "nearest",
  "page": 1,
  "limit": 10
}
Reponse minimale
{
  "success": true,
  "message": "Departs trouves",
  "data": {
    "data": [
      {
        "id": "departure-id-abj-bke-1430",
        "price": 4000,
        "distance_km": 1.8,
        "capacity_remaining": 22,
        "company": {
          "id": "company-id-utb",
          "name": "UTB"
        }
      }
    ],
    "meta": {
      "total": 1,
      "per_page": 10,
      "last_page": 1
    },
    "search_expansion": {
      "current_radius_km": 10,
      "next_allowed_radius_km": 20,
      "can_expand": true,
      "max_radius_km": 60
    }
  }
}
22

Voir le détail d'un départ

Afficher la gare physique, la présence compagnie, les contacts, les horaires, le véhicule, les places et le prix.

Bearer client
GET /api/trip-departures/:id/details Voir dans Swagger
Types attendus Utiliser ces types et emplacements pour envoyer des valeurs conformes.
Champ Type Source Obligatoire Description
Authorization string header oui Bearer token du client connecte.
id uuid path oui ID du depart a consulter.
Payload minimal

Aucun body requis. Utiliser les query params ou l'identifiant dans l'URL.

Reponse minimale
{
  "success": true,
  "message": "Detail depart recupere",
  "data": {
    "id": "departure-id-abj-bke-1430",
    "price": 4000,
    "vehicle_label": "Bus VVIP",
    "transport_hub": {
      "name": "Gare d'Adjame",
      "photo_url": "https://cdn.ticketnet.ci/hubs/adjame.jpg"
    },
    "company_hub": {
      "display_name": "UTB - Adjame",
      "phone": "0102030405"
    }
  }
}
Rappel de cohérence :
un départ doit pointer vers deux présences compagnie appartenant à la même compagnie que le trajet, et les gares physiques associées doivent correspondre aux localisations d'origine et de destination du trajet.