Introduction

L'API TAAMA expose, à un site web externe, le même moteur de réservation que l'application TAAMA : recherche d'itinéraires, réservation, paiement et suivi — pour la billetterie voyageurs (bus, train, vols locaux), les colis et le fret. Elle est faite pour être appelée serveur à serveur, depuis le backend du site qui l'intègre (jamais directement depuis le navigateur d'un visiteur).

Besoin d'un point de départ prêt à l'emploi ? Un site modèle PHP complet (recherche → passagers → paiement → billet) t'est fourni à l'activation de ta licence. Cette page documente l'API elle-même.

Authentification

Chaque requête vers public_api.php doit porter deux en-têtes HTTP, obtenus depuis l'onglet API TAAMA de ton tableau de bord :

En-têteRôle
X-Taama-Api-KeyIdentifiant public de ton abonnement (commence par ak_live_).
X-Taama-Api-SecretSecret privé, affiché une seule fois à la génération ou régénération — ne doit jamais apparaître dans du code exécuté côté navigateur.
⚠️ Le secret ne doit jamais transiter par le navigateur, une app mobile ou un dépôt de code public. public_api.php n'envoie volontairement aucun en-tête CORS : un navigateur ne peut pas l'appeler directement, ce qui protège ton secret même en cas d'erreur d'intégration.

Une authentification absente ou invalide renvoie HTTP 401 ; une licence expirée ou désactivée renvoie HTTP 403 avec un message explicite.

Format des requêtes & réponses

URL de base : https://api.taama.vip/public_api.php

Chaque action se passe dans le paramètre action. Deux formats acceptés :

  • POST avec un corps JSON (Content-Type: application/json) — recommandé.
  • GET avec les paramètres en query string.

Toute réponse est un JSON {"ok": true|false, "data": ..., "error": "..."}, en HTTP 200 dans la plupart des cas (le champ ok porte le résultat réel) — sauf pour un problème d'authentification (401) ou de licence (403).

Périmètre (scope)

Chaque abonné a un périmètre fixé à l'activation, non modifiable par l'API elle-même :

ScopeQuiEffet
own_companyCompagnie de transportNe voit et ne peut vendre que ses propres itinéraires/convois/services colis/fret.
globalAgent de voyageVoit et peut vendre pour toutes les compagnies actives sur TAAMA.

De plus, chaque réservation/colis/fret créé via l'API est marqué avec l'identifiant de l'abonné qui l'a créé : un abonné ne peut ensuite consulter, payer ou annuler que ce qu'il a lui-même créé — isolation totale, y compris entre deux sites d'une même compagnie.

Référence des actions

GET/POSTmeta

Point de départ de toute intégration : villes desservies, compagnies visibles pour cet abonné, devise, disponibilité de Paystack.

Aucun paramètre requis. Réponse : currency, platformName, scope, companies[], cities[], vehicleTypes, paystackEnabled, paystackPublicKey, cancellationCashFeePct, parcelCollectionFlatFee, freightCollectionFlatFee, freightDeliveryFlatFee, freightRateTypes.

Recherche & départs

POSTroutes.search

ParamètreRequisDescription
originCityOuiVille de départ.
destinationCityOuiVille d'arrivée.
typeNonbus (défaut) · train · avion · fret.

Renvoie les itinéraires actifs correspondants, avec routeId, reversed (si le trajet retour a été trouvé), company et classes[] (tarifs).

POSTroutes.convois

ParamètreRequisDescription
routeIdOuiIdentifiant renvoyé par routes.search.
reversedNonSens du trajet (voir routes.search).
dateOuiDate du voyage, AAAA-MM-JJ.

Renvoie les départs (convois) disponibles à cette date, avec places restantes déjà calculées.

POSTroutes.seatmap

ParamètreRequisDescription
convoiIdOuiIdentifiant renvoyé par routes.convois.
dateOuiDate du voyage.
classIdNonPour renvoyer le prix par siège si la classe est connue.

Renvoie seatMap.enabled (le plan de sièges est-il activé pour ce convoi ?) et seatMap.seats[] le cas échéant.

Réservations (billetterie)

POSTbookings.create

Crée une réservation en aller simple (voir limitations pour l'aller-retour). Un convoiId précis est obligatoire.

ParamètreRequisDescription
routeId, classId, convoiId, travelDateOuiRésultat de routes.search/routes.convois.
quantityNonNombre de passagers (1 à 20, défaut 1).
seatNumbersSelon plan de siègesTableau d'un numéro de siège par passager — obligatoire si seatMap.enabled.
contactName, contactPhoneOuiAcheteur — sert à créer/retrouver son compte TAAMA. Téléphone au format +225xxxxxxxxx ou chiffres seuls (8 à 15 caractères).
contactEmailNonSi absent, un code PIN est généré (voir la réponse, champ newPin) — à transmettre toi-même au client.
emergencyContactPhoneNonDéfaut : contactPhone.
passengerNamesNonTableau d'un nom par passager (défaut : contactName).
passengerCivility[], passengerPieceType[], passengerPieceNumber[], passengerFirstName[], passengerLastName[]NonUn tableau par champ, indexé comme quantity (ex. passengerFirstName: ["Awa","Yao"]).
boardingSalePointIdNonPoint d'embarquement alternatif, parmi les arrêts de l'itinéraire.

Réponse : bookings[] (une entrée par passager, chacune avec ref, status: "en_attente_paiement", price) et contact (dont newPin si généré).

Pour un abonné agent (scope: global), la commission de parrainage habituelle est créditée automatiquement dès le paiement confirmé — rien à faire de spécial côté intégration.

POSTbookings.get

Paramètre : id. Renvoie le récapitulatif du billet (uniquement s'il a été créé par ton abonnement).

POSTbookings.pay

ParamètreRequisDescription
ids (ou id)OuiUn ou plusieurs identifiants de réservation (billets d'un même groupe).
methodOuipaystack ou wave.
referenceOuiRéférence de la transaction à vérifier.

paystack : la référence est revérifiée serveur à serveur directement auprès de Paystack (statut ET montant) — jamais sur la seule foi du navigateur. wave (ou tout paiement direct) : la référence est enregistrée comme preuve à vérifier, le billet passe preuve_a_verifier et la compagnie la confirme depuis son tableau de bord existant.

POSTbookings.cancel

Paramètre : id. Applique exactement la politique d'annulation configurée par la compagnie (remboursement en crédit ou en espèces, selon ses réglages) — aucun moyen de la contourner via l'API.

Colis

POSTparcels.services

Paramètres : originCity, destinationCity (requis). Renvoie les services de livraison disponibles, chacun avec ses categories[] et tarifs.

POSTparcels.create

ParamètreRequisDescription
serviceId, originCity, destinationCityOuiRésultat de parcels.services.
categoryIdNonSinon le tarif de base du service s'applique (forfait ou au kg selon weight).
senderName, senderPhoneOuiExpéditeur.
senderEmailNon—
recipientName, recipientPhoneOuiDestinataire.
description, weightNonUtile si tarification au kg.
declaredValueNonDéclenche une assurance calculée automatiquement.
collectionRequested, collectionAddressNonEnlèvement à domicile (adresse requise si demandé).

POSTparcels.pay

Paramètres : id, method (paystack|wave), reference — même logique de vérification que bookings.pay.

POSTparcels.get

Paramètre : id. Renvoie le colis avec son historique de suivi (trackingEvents).

Fret

POSTfreight.create

ParamètreRequisDescription
convoiIdOuiConvoi de type fret (résultat de routes.convois pour un itinéraire type=fret).
rateType, quantityOuiType de tarif proposé par le convoi (poids, volume...) et quantité correspondante.
goodsDescription, travelDateOui—
goodsCategory, packageCountNon—
contactName, contactPhone, recipientName, recipientPhoneOuiExpéditeur et destinataire.
collectionRequested/collectionAddress, deliveryRequested/deliveryAddressNonEnlèvement et/ou livraison à domicile (adresse requise si demandé).
declaredValueNonAssurance calculée automatiquement.

POSTfreight.pay

Mêmes paramètres et logique que bookings.pay/parcels.pay.

POSTfreight.get

Paramètre : id.

Erreurs & limites

Code HTTPSignification
200Requête traitée — regarder le champ ok du JSON pour le résultat réel.
401En-têtes d'authentification absents ou clé/secret invalides.
403Authentification valide mais licence inactive, expirée ou suspendue.

Les tentatives d'authentification invalides répétées sont limitées en débit (anti brute-force) par clé publique et par IP — une intégration normale ne les rencontrera jamais.

Exemple complet

Recherche d'itinéraires en curl :

curl -X POST "https://api.taama.vip/public_api.php?action=routes.search" \
  -H "X-Taama-Api-Key: ak_live_xxxxxxxxxxxx" \
  -H "X-Taama-Api-Secret: sk_live_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"originCity":"Abidjan","destinationCity":"Bouaké","type":"bus"}'

Le site modèle fourni encapsule tout appel dans une seule fonction (lib/ApiClient.php) :

function taamaApi($action, $params = []) {
    $ch = curl_init(TAAMA_API_URL . '?action=' . urlencode($action));
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($params),
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'X-Taama-Api-Key: ' . TAAMA_API_KEY,
            'X-Taama-Api-Secret: ' . TAAMA_API_SECRET,
        ],
    ]);
    $raw = curl_exec($ch);
    curl_close($ch);
    return json_decode($raw, true) ?: ['ok' => false, 'error' => 'Réponse invalide.'];
}

Limitations connues (v1)

  • Aller-retour : pas de réservation combinée en un seul appel — faire deux appels bookings.create (un par sens), avec le même contact.
  • Réservation "gare à gare" : non disponible via l'API — un convoiId précis (donc un horaire) est toujours requis, contrairement à l'application TAAMA elle-même.
  • Listing en masse : pas d'action pour lister toutes tes réservations d'un coup — conserve les identifiants renvoyés à la création de ton côté (base de données de ton site).
Une question technique ? Écris à api@taama.vip ou passe par le formulaire de souscription si tu n'as pas encore de licence active.