Démarrage rapide
1. Un compte marchand
Créez votre compte marchand dans l'app DROPP (ou demandez-le à notre équipe).
2. Une clé de test
Dans l'app : Profil → Intégration e-commerce → Nouvelle clé, option « Clé de test ».
3. Vos premiers colis
Affichez les relais et le prix au panier, créez les colis à la commande, faites-les avancer avec le simulateur.
4. En réel
Créez une clé réelle, enregistrez votre URL de webhook en HTTPS, et c'est parti.
Adresse de l'API : https://api.dropp237.com/api/v1
Comment ça marche
- 1Au panier, votre site affiche les points relais DROPP et le prix de la livraison, calculé d'après le poids de la commande.
- 2L'acheteur choisit son relais et paie votre boutique : en ligne, ou au retrait (contre-remboursement).
- 3Votre site crée le colis par l'API. Il apparaît « à payer » dans votre app DROPP.
- 4Vous payez la livraison à DROPP dans l'app, ou au relais en déposant le colis. Rien ne part sans être payé.
- 5DROPP transporte le colis. L'acheteur reçoit un code par SMS et le retire au relais choisi.
- 6Paiement au retrait : l'acheteur paie au relais et vous recevez la totalité par Mobile Money, sans aucune retenue.
| Situation | Ce qui se passe |
|---|---|
| Colis non payé ni déposé sous 7 jours | Supprimé automatiquement (webhook shipment.deleted). |
| Colis payé mais jamais déposé sous 14 jours | Annulé, et les frais vous sont remboursés. |
| Colis non retiré par l'acheteur | Il revient au relais de départ. Vous le récupérez avec votre code retours (dans votre profil) en payant 50 % du prix aller. |
Authentification
Chaque appel porte votre clé secrète dans l'en-tête Authorization. Appelez l'API depuis votre serveur uniquement : la clé ne doit jamais apparaître dans le navigateur ni dans une app mobile.
Authorization: Bearer dropp_sk_live_xxxxxxxxxxxxxxxx| Clé | Usage |
|---|---|
dropp_sk_test_… | Mode test : vrais relais et vrais prix, colis fictifs (TST-…), aucun paiement. |
dropp_sk_live_… | Mode réel : vrais colis (DRP-…). |
Les clés se créent et se révoquent dans l'app marchand, avec un code SMS. Le secret n'est affiché qu'une fois : gardez-le dans une variable d'environnement. Pour éviter un doublon si vous réessayez une requête, ajoutez l'en-tête Idempotency-Key : la même requête renvoyée avec la même clé reçoit la première réponse.
Points relais
GET/ecommerce/relay-points?city=Douala
Les relais ouverts, à proposer à l'acheteur. Gardez l'id du relais choisi : il sert à créer le colis.
curl "https://api.dropp237.com/api/v1/ecommerce/relay-points?city=Douala" \
-H "Authorization: Bearer $DROPP_API_KEY"[
{
"id": "8f0c2c1e-5b7a-4a52-9d1e-2b8f3c4d5e6f",
"name": "DROPP Akwa",
"city": "Douala",
"neighborhood": "Akwa",
"address": "Papeterie du Centre, boulevard de la Liberté",
"latitude": 4.0511,
"longitude": 9.7043,
"phone_number": "+237690000000",
"photo_url": null
}
]Prix et catégories
GET/ecommerce/quote?weight=1.5
Envoyez le poids total de la commande en kg : DROPP choisit la catégorie. Pour un objet léger mais encombrant, imposez-la avec package_size=M ou L. Le prix est toujours celui entre deux villes.
| Catégorie | Poids maximum | Prix |
|---|---|---|
| S | 1 kg | 2 000 FCFA |
| M | 5 kg | 2 750 FCFA |
| L | 15 kg | 3 500 FCFA |
curl "https://api.dropp237.com/api/v1/ecommerce/quote?weight=1.5" \
-H "Authorization: Bearer $DROPP_API_KEY"
# {"package_size": "M", "weight": 1.5, "shipping_fee": 2750.0, "currency": "XAF"}Créer un colis
POST/ecommerce/shipments
À appeler quand la commande est validée. Le colis est créé « à payer » : vous le payez dans l'app DROPP ou au relais en le déposant.
| Champ | Description |
|---|---|
external_reference | Votre n° de commande. Un seul colis par commande : un deuxième appel renvoie 409. |
recipient.name | Nom de l'acheteur. |
recipient.phone_number | Numéro camerounais : il reçoit le code de retrait par SMS. |
destination_relay_id | Relais choisi par l'acheteur. |
weight | Poids total en kg (ou package_size : S, M, L). |
cod_amount | Montant que l'acheteur paie au relais (0 si payé en ligne). Il vous est reversé en entier. |
content_description | Facultatif : le contenu du colis. |
curl -X POST "https://api.dropp237.com/api/v1/ecommerce/shipments" \
-H "Authorization: Bearer $DROPP_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-CMD-1001" \
-d '{
"external_reference": "CMD-1001",
"recipient": { "name": "Paul Mbarga", "phone_number": "677112233" },
"destination_relay_id": "8f0c2c1e-5b7a-4a52-9d1e-2b8f3c4d5e6f",
"weight": 1.5,
"cod_amount": 0,
"content_description": "Baskets"
}'{
"tracking_id": "DRP-3F6D45992EFD",
"external_reference": "CMD-1001",
"status": "CREATED",
"package_size": "M",
"weight": 1.5,
"shipping_fee": 2750.0,
"currency": "XAF",
"fee_paid": false,
"cod_amount": 0.0,
"cod_status": "NONE",
"recipient_name": "Paul Mbarga",
"recipient_phone": "+237677112233",
"destination_relay": { "name": "DROPP Akwa", "city": "Douala", "...": "..." },
"expires_in_seconds": 604800,
"timeline": [{ "status": "CREATED", "relay_point_name": null, "created_at": "…" }],
"test_mode": false
}Suivre et annuler
GET/ecommerce/shipments/{tracking_id}
GET/ecommerce/shipments?external_reference=CMD-1001
DELETE/ecommerce/shipments/{tracking_id}
Le détail donne le statut, l'historique, le relais, le contre-remboursement et son versement. L'annulation n'est possible que tant que la livraison n'est pas payée ; ensuite, contactez le support.
# One parcel
curl "https://api.dropp237.com/api/v1/ecommerce/shipments/DRP-3F6D45992EFD" -H "Authorization: Bearer $DROPP_API_KEY"
# By order number
curl "https://api.dropp237.com/api/v1/ecommerce/shipments?external_reference=CMD-1001" -H "Authorization: Bearer $DROPP_API_KEY"
# Cancel (only while the fee is not paid)
curl -X DELETE "https://api.dropp237.com/api/v1/ecommerce/shipments/DRP-3F6D45992EFD" -H "Authorization: Bearer $DROPP_API_KEY"Statuts
| Statut | Signification |
|---|---|
CREATED | Créé, livraison à payer |
PAID | Livraison payée, à déposer au relais |
DROPPED_AT_ORIGIN | Déposé au relais de départ |
PICKED_UP / IN_CONSOLIDATION_BAG / IN_TRANSIT | En route |
DROPPED_AT_DESTINATION | Arrivé au relais, en cours de réception |
READY_FOR_PICKUP | Prêt : l'acheteur a reçu son code |
DELIVERED | Remis à l'acheteur |
RETURNED / RETURN_IN_TRANSIT | Non retiré : retour vers le relais de départ |
RETURN_AT_ORIGIN | Revenu au relais de départ, à récupérer |
RETURNED_TO_SENDER | Rendu à la boutique |
CANCELLED / LOST / DAMAGED | Annulé, perdu ou endommagé : le support vous contacte |
Webhooks
DROPP appelle votre URL à chaque événement : plus besoin d'interroger l'API. Enregistrez une URL HTTPS publique ; la réponse contient le secret de signature, affiché une seule fois.
curl -X PUT "https://api.dropp237.com/api/v1/ecommerce/webhook" \
-H "Authorization: Bearer $DROPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://ma-boutique.cm/webhooks/dropp"}'
# {"url": "...", "test_mode": false, "secret": "whsec_..."} <- keep the secret
# Send a test event
curl -X POST "https://api.dropp237.com/api/v1/ecommerce/webhook/test" -H "Authorization: Bearer $DROPP_API_KEY"| Événement | Quand |
|---|---|
shipment.status_changed | Chaque changement de statut (data.previous_status) |
shipment.payment_failed | Le paiement de la livraison a échoué |
shipment.cod_paid | L'acheteur a payé au relais |
shipment.deleted | Colis non payé supprimé (data.reason : expired ou cancelled) |
ping | Test demandé par vous |
POST /webhooks/dropp
Dropp-Signature: t=1760781120,v1=5f2c…
Dropp-Event: shipment.status_changed
Dropp-Event-Id: evt_3f1c…
{
"id": "evt_3f1c…",
"type": "shipment.status_changed",
"created_at": "2026-10-18T09:12:00+00:00",
"test_mode": false,
"data": {
"previous_status": "IN_TRANSIT",
"shipment": { "tracking_id": "DRP-3F6D45992EFD", "external_reference": "CMD-1001", "status": "READY_FOR_PICKUP", "...": "..." }
}
}Vérifiez toujours la signature avant de croire un appel : HMAC-SHA256 du texte « t.corps brut » avec votre secret, comparé à v1, et t de moins de 5 minutes.
import crypto from "node:crypto";
import express from "express";
const app = express();
// The signature is computed on the raw body: do not parse it before.
app.post("/webhooks/dropp", express.raw({ type: "application/json" }), (req, res) => {
const header = req.get("Dropp-Signature") ?? "";
const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const expected = crypto
.createHmac("sha256", process.env.DROPP_WEBHOOK_SECRET)
.update(`${t}.${req.body}`)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
if (!v1 || !fresh || !crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body);
// Ignore an event.id already handled, then update the order.
res.sendStatus(200);
});Mode test
Avec une clé de test, tout fonctionne comme en réel (relais, prix, webhooks), mais les colis sont fictifs : aucun relais ne les voit, aucun paiement n'est demandé. Faites-les avancer vous-même :
POST/ecommerce/test/shipments/{tracking_id}/simulate
| action | Effet |
|---|---|
advance | Étape suivante : payé, déposé, en route, prêt au retrait, livré (le paiement au retrait passe alors à payé) |
expire | Le colis non payé expire et est supprimé |
# Test key: dropp_sk_test_...
curl -X POST "https://api.dropp237.com/api/v1/ecommerce/test/shipments/TST-7BABF5615428/simulate" \
-H "Authorization: Bearer $DROPP_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"action": "advance"}'Erreurs
Une erreur renvoie un code HTTP et une phrase claire, à afficher telle quelle : {"detail": "…"}
| Code | Signification |
|---|---|
400 | Donnée refusée (relais fermé, numéro invalide, colis trop lourd…) |
401 | Clé absente, inconnue ou révoquée |
403 | Compte marchand bloqué, ou action réservée aux clés de test |
404 | Colis introuvable (ou d'un autre marchand) |
409 | Commande déjà envoyée, ou paiement en cours |
422 | Champ manquant ou mal formé |
Mise en production
- ✓La clé réelle est dans une variable d'environnement de votre serveur, jamais dans le code ni le navigateur.
- ✓Chaque création de colis envoie external_reference et Idempotency-Key.
- ✓Le webhook est en HTTPS, vérifie la signature et ignore les événements déjà traités.
- ✓Le prix affiché au panier vient de /ecommerce/quote.
- ✓Les erreurs de l'API sont affichées au marchand, pas avalées.
Une question sur l'intégration ?
Notre équipe vous aide à connecter votre boutique, quelle que soit sa plateforme.