API Partenaire · Référence v1

Créez des livraisons directement depuis votre système

Envoyez un point de retrait et une destination : Carygoo calcule le prix à partir de la distance réelle, attribue un livreur automatiquement, et vous tient informé en temps réel par webhook.

Sommaire

Authentification

Chaque requête vers partner-api/v1/* s'authentifie avec une paire clé/secret propre à votre compte.

HeaderDescription
X-Api-KeyVotre clé publique — pk_live_...
X-Api-SecretVotre secret — ne l'exposez jamais côté client ou mobile

Ces identifiants se génèrent depuis votre tableau de bord Carygoo, section Intégration API. Le secret n'est affiché qu'une seule fois, au moment de la génération — Carygoo ne le stocke jamais en clair et ne peut pas vous le redonner.

Identifiants invalides

Une requête sans ces headers, ou avec une clé révoquée, reçoit une réponse 401 :

HTTP/1.1 401 Unauthorized
{
  "error": {
    "code": "invalid_api_credentials",
    "message": "Clé API ou secret invalide."
  }
}

Limite de débit : 120 requêtes/minute par clé. Au-delà, réponse 429 Too Many Requests.

Types de véhicule

GET/partner-api/v1/vehicle-types

Chaque type porte sa propre grille tarifaire, non exposée ici — le prix final est toujours calculé par Carygoo à la création de la livraison.

{
  "vehicle_types": [
    { "id": 1, "libelle": "Moto", "description": "Petits colis, documents" },
    { "id": 2, "libelle": "Voiture", "description": "Colis moyens" }
  ]
}

Recherche d'adresse (optionnel)

Pas besoin de gérer votre propre clé Google Maps : Carygoo propose, par défaut, un proxy vers Google Place Autocomplete. Facultatif — vous pouvez continuer à résoudre vos adresses de votre côté et envoyer directement des coordonnées à la création de livraison.

GET/partner-api/v1/places/autocomplete?input=...&session_token=...
{
  "suggestions": [
    { "description": "Akwa, Douala, Cameroon", "place_id": "ChIJ6Yas2F8SYRARJq4txF-eIIw" }
  ]
}

Non facturé. Générez un session_token (un UUID de votre côté) au début de la saisie et réutilisez-le pour tous les appels autocomplete de la même recherche.

GET/partner-api/v1/places/details?place_id=...&session_token=...
{
  "address": "Akwa I, Douala, Cameroon",
  "lat": 4.0531425, "lng": 9.6995823,
  "wallet_balance_after": 48500
}

Facturé (action place_lookup, cf. section 8) — c'est cet appel qui clôt la session et engage un coût réel, jamais autocomplete. 402 insufficient_wallet_balance si le solde ne le permet pas.

Créer une livraison

POST/partner-api/v1/deliveries

Requête

ChampTypeObligatoireDescription
pickup.addressstringOuiAdresse texte du point de retrait
pickup.lat / pickup.lngnumberOuiCoordonnées du point de retrait
pickup.contact_namestringOuiNom à contacter au retrait
pickup.contact_phonestringOuiTéléphone à contacter au retrait
dropoff.addressstringOuiAdresse texte de la destination
dropoff.lat / dropoff.lngnumberOuiCoordonnées de la destination
dropoff.contact_namestringOuiNom du destinataire
dropoff.contact_phonestringOuiTéléphone du destinataire
category_idintegerOuiType de véhicule/colis — voir section 2
order_itemsarrayNonArticles transportés — [{label, quantity}]
notesstringNonNote libre pour le livreur (code d'accès, étage...)
{
  "pickup": {
    "address": "Akwa, Douala",
    "lat": 4.0483, "lng": 9.7043,
    "contact_name": "Boutique Akwa",
    "contact_phone": "699000001"
  },
  "dropoff": {
    "address": "Bonapriso, Douala",
    "lat": 4.0221, "lng": 9.6987,
    "contact_name": "Jean Client",
    "contact_phone": "677000002"
  },
  "category_id": 1,
  "notes": "Sonner à l'interphone"
}

Réponse — 201 Created

{
  "delivery_id": "8f14e45f-ceea-467e-bd97-4b3a1c1e0f6a",
  "status": "driver_assigned",
  "distance_km": 4.8, "duration_min": 14.2,
  "price": { "amount": 1220, "currency": "XAF" },
  "wallet_balance_after": 48490
}

delivery_id est l'identifiant public à utiliser pour le suivi et l'annulation.

Erreurs

HTTPCodeSignification
422validation_errorChamp manquant ou invalide
402subscription_requiredAbonnement inactif ou quota épuisé
402insufficient_wallet_balanceSolde du portefeuille API insuffisant — voir section 8
502distance_calculation_failedDistance introuvable entre les deux points
500delivery_creation_failedErreur technique — le quota et les frais API ne sont pas décomptés

Attribution du livreur

À la création, Carygoo cherche un livreur disponible en deux temps :

1 · Votre flotte

Vos chauffeurs/véhicules déclarés dans votre tableau de bord sont toujours essayés en premier.

2 · Pool global Carygoo

Si aucun de vos chauffeurs n'est libre, bascule automatique sur le réseau Carygoo — sauf si désactivé.

Ce réglage (fallback_to_global_pool, activé par défaut) se configure depuis votre tableau de bord, section Intégration API.

Si aucun livreur n'est trouvé immédiatement, la livraison passe au statut no_driver_found et Carygoo continue de chercher automatiquement (tentatives espacées de 30s à 5min) — vous êtes notifié par webhook dès qu'un livreur est trouvé.

Suivre / annuler

GET/partner-api/v1/deliveries/{delivery_id}
{
  "delivery_id": "8f14e45f-ceea-467e-bd97-4b3a1c1e0f6a",
  "status": "picked_up",
  "price": { "amount": 1220, "currency": "XAF" },
  "driver": {
    "name": "Paul Mbarga",
    "phone": "690000000",
    "vehicle_plate": "LT-1234-AB",
    "position": { "lat": 4.031, "lng": 9.701 }
  }
}
POST/partner-api/v1/deliveries/{delivery_id}/cancel

Possible uniquement avant récupération par le livreur (pending, driver_assigned, no_driver_found) — sinon 409 delivery_not_cancelable.

Cycle de vie

pendingdriver_assignedpicked_updelivered

↳ à tout moment avant picked_up : canceled

↳ si aucun livreur : no_driver_found → retrouvé → driver_assigned

Webhooks

Configurez une URL de callback depuis votre tableau de bord (section Intégration API). Carygoo y envoie un POST JSON à chaque événement.

ÉvénementDéclencheur
delivery.status_changedLe statut de la livraison change
delivery.position_updatedPosition GPS du livreur — au plus 1×/10s par livraison

Payload

{
  "event": "delivery.status_changed",
  "data": {
    "delivery_id": "8f14e45f-...",
    "status": "driver_assigned",
    "driver": { "name": "Paul Mbarga", ... }
  }
}

Vérifier la signature

Chaque requête inclut X-Carygoo-Event, X-Carygoo-Timestamp et X-Carygoo-Signature — un HMAC-SHA256 de timestamp + "." + corps_brut avec votre webhook_secret (affiché une seule fois, comme votre api_secret).

PHP

$expected = hash_hmac('sha256', $timestamp.'.'.$rawBody, $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}

Node.js

const expected = crypto
  .createHmac('sha256', secret)
  .update(`${timestamp}.${rawBody}`)
  .digest('hex');

if (!crypto.timingSafeEqual(
  Buffer.from(expected), Buffer.from(signature)
)) return res.status(401).end();

Accusé de réception

Répondez 2xx sous 10s. En cas d'échec, Carygoo retente jusqu'à 5 fois (10s, 30s, 1min, 5min, 15min). L'historique de tous les envois est consultable depuis votre tableau de bord.

Portefeuille API

L'usage de l'API a un coût réel pour Carygoo (Google Distance Matrix à chaque livraison, Google Places si vous utilisez la recherche d'adresse, infrastructure) — distinct du prix de la livraison elle-même, qui rémunère le livreur.

Par livraison créée

0 FCFA

Google 0 + Infra 0 + Marge 0

Par recherche d'adresse

0 FCFA

Google 0 + Infra 0 + Marge 0

Rechargez votre portefeuille en Mobile Money (MTN/Orange, via Dohone — le même moyen déjà utilisé pour votre abonnement) depuis votre tableau de bord. Un solde négatif (dette) est toléré jusqu'à un plafond défini par Carygoo — au-delà, l'API renvoie 402 insufficient_wallet_balance jusqu'à recharge.

Devise

Tous les montants sont exprimés en XAF (Francs CFA), en unité entière.