Intégrer
Devis et prix
Comment le prix se calcule, ce qui le fait varier, et comment afficher un tarif avant que le client ne soit identifié.
Un prix indicatif, sans compte
simulatePrice rend un ordre de grandeur sans clé d'API et sans rien réserver. C'est l'appel à faire dans un tunnel de commande, avant que le client ne soit identifié.
# 1. Devis — `city` est le QUARTIER, pas la ville.
QUOTE=$(curl -s -X POST "$RAPIDY_API_URL/v1/quotes" \
-H "X-Api-Key: $RAPIDY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pickup": { "city": "Médina", "address": "Rue 11 x Blaise Diagne" },
"dropoff": { "city": "Ouakam", "address": "Cité Avion, villa 12" },
"parcel": { "weight_kg": 2 }
}')
QUOTE_ID=$(echo "$QUOTE" | jq -r .quote_id)
# 2. Envoi — `external_order_id` est VOTRE référence.
SHIPMENT=$(curl -s -X POST "$RAPIDY_API_URL/v1/shipments" \
-H "X-Api-Key: $RAPIDY_API_KEY" \
-H "Content-Type: application/json" \
-d "{ \"quote_id\": \"$QUOTE_ID\", \"external_order_id\": \"CMD-2026-42\" }")
SHIPMENT_ID=$(echo "$SHIPMENT" | jq -r .shipment_id)
# 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
curl -s -X POST "$RAPIDY_API_URL/v1/shipments/$SHIPMENT_ID/mark-ready" \
-H "X-Api-Key: $RAPIDY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "by": "mon-back-office" }'// 1. Devis — `city` est le QUARTIER, pas la ville.
const quote = await rapidy.createQuote({
pickup: { city: 'Médina', address: 'Rue 11 x Blaise Diagne' },
dropoff: { city: 'Ouakam', address: 'Cité Avion, villa 12' },
parcel: { weightKg: 2 },
});
// 2. Envoi — `externalOrderId` est VOTRE référence de commande.
const shipment = await rapidy.createShipment({
quoteId: quote.id,
externalOrderId: 'CMD-2026-42',
});
// 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
await rapidy.markReady(shipment.id, 'mon-back-office');
console.log(shipment.publicTrackingUrl); // à partager au client final# 1. Devis — `city` est le QUARTIER, pas la ville.
quote = rapidy.create_quote(
pickup={"city": "Médina", "address": "Rue 11 x Blaise Diagne"},
dropoff={"city": "Ouakam", "address": "Cité Avion, villa 12"},
parcel={"weight_kg": 2},
)
# 2. Envoi — `external_order_id` est VOTRE référence de commande.
shipment = rapidy.create_shipment(
quote_id=quote["quote_id"],
external_order_id="CMD-2026-42",
)
# 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
rapidy.mark_ready(shipment_id=shipment["shipment_id"], by="mon-back-office")// 1. Devis — `city` est le QUARTIER, pas la ville.
$quote = $rapidy->createQuote([
'pickup' => ['city' => 'Médina', 'address' => 'Rue 11 x Blaise Diagne'],
'dropoff' => ['city' => 'Ouakam', 'address' => 'Cité Avion, villa 12'],
'parcel' => ['weight_kg' => 2],
]);
// 2. Envoi — `external_order_id` est VOTRE référence de commande.
$shipment = $rapidy->createShipment([
'quote_id' => $quote['quote_id'],
'external_order_id' => 'CMD-2026-42',
]);
// 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
$rapidy->markReady($shipment['shipment_id'], by: 'mon-back-office');# 1. Devis — `city` est le QUARTIER, pas la ville.
quote = rapidy.create_quote(
pickup: { city: 'Médina', address: 'Rue 11 x Blaise Diagne' },
dropoff: { city: 'Ouakam', address: 'Cité Avion, villa 12' },
parcel: { weight_kg: 2 }
)
# 2. Envoi — `external_order_id` est VOTRE référence de commande.
shipment = rapidy.create_shipment(
quote_id: quote['quote_id'],
external_order_id: 'CMD-2026-42'
)
# 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
rapidy.mark_ready(shipment_id: shipment['shipment_id'], by: 'mon-back-office')ctx := context.Background()
// 1. Devis — `city` est le QUARTIER, pas la ville.
quote, err := client.CreateQuote(ctx, map[string]any{
"pickup": map[string]any{"city": "Médina", "address": "Rue 11 x Blaise Diagne"},
"dropoff": map[string]any{"city": "Ouakam", "address": "Cité Avion, villa 12"},
"parcel": map[string]any{"weight_kg": 2},
})
// 2. Envoi — `external_order_id` est VOTRE référence de commande.
shipment, err := client.CreateShipment(ctx, map[string]any{
"quote_id": quote["quote_id"],
"external_order_id": "CMD-2026-42",
})
// 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
_, err = client.MarkReady(ctx, shipment["shipment_id"].(string), "mon-back-office")// 1. Devis — `city` est le QUARTIER, pas la ville.
Map<String, Object> quote = rapidy.createQuote(Map.of(
"pickup", Map.of("city", "Médina", "address", "Rue 11 x Blaise Diagne"),
"dropoff", Map.of("city", "Ouakam", "address", "Cité Avion, villa 12"),
"parcel", Map.of("weight_kg", 2)));
// 2. Envoi — `external_order_id` est VOTRE référence de commande.
Map<String, Object> shipment = rapidy.createShipment(Map.of(
"quote_id", quote.get("quote_id"),
"external_order_id", "CMD-2026-42"));
// 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
rapidy.markReady((String) shipment.get("shipment_id"), "mon-back-office");// 1. Devis — `city` est le QUARTIER, pas la ville.
var quote = await rapidy.CreateQuoteAsync(new Dictionary<string, object>
{
["pickup"] = new Dictionary<string, object> { ["city"] = "Médina", ["address"] = "Rue 11 x Blaise Diagne" },
["dropoff"] = new Dictionary<string, object> { ["city"] = "Ouakam", ["address"] = "Cité Avion, villa 12" },
["parcel"] = new Dictionary<string, object> { ["weight_kg"] = 2 },
});
// 2. Envoi — `external_order_id` est VOTRE référence de commande.
var shipment = await rapidy.CreateShipmentAsync(new Dictionary<string, object>
{
["quote_id"] = quote["quote_id"]!,
["external_order_id"] = "CMD-2026-42",
});
// 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
await rapidy.MarkReadyAsync((string)shipment["shipment_id"]!, "mon-back-office");// 1. Devis — `city` est le QUARTIER, pas la ville.
final quote = await rapidy.createQuote(CreateQuoteRequest(
pickup: Address(city: 'Médina', address: 'Rue 11 x Blaise Diagne'),
dropoff: Address(city: 'Ouakam', address: 'Cité Avion, villa 12'),
parcel: Parcel(weightKg: 2),
));
// 2. Envoi — `externalOrderId` est VOTRE référence de commande.
final shipment = await rapidy.createShipment(
CreateShipmentRequest.fromQuote(quoteId: quote.id, externalOrderId: 'CMD-2026-42'),
);
// 3. Prêt à enlever — SANS CE GESTE, AUCUNE COURSE NE PART.
await rapidy.markReady(shipmentId: shipment.id, by: 'mon-back-office');
Ce n'est pas un devis : rien n'est réservé, aucun identifiant n'est rendu, et le prix peut différer du devis ferme. Pour un prix opposable, appelez createQuote.
Un prix ferme : le devis
createQuote rend un prix garanti jusqu'à expiresAt. C'est ce devis que createShipment consomme.
Un devis périmé est refusé : redemandez-en un plutôt que de réutiliser l'ancien.
Ce qui fait varier le prix
Le quartier, d'abord
city est le quartier. C'est lui qui porte la zone
tarifaire. « Dakar » n'est pas un quartier : envoyer la ville fait sortir le tarif de
repli, le plus élevé, et le client paie la différence.
Les coordonnées, si vous les avez
Joignez coords (lat, lng) sur le retrait et la livraison : le prix suit alors la distance réelle plutôt que la zone. C'est plus juste dans les deux sens — pour les trajets courts intra-quartier comme pour les longues traversées.
Le poids
parcel.weight_kg entre dans le calcul. Une valeur absente est traitée comme un colis standard ; une valeur fausse vous expose à un ajustement à l'enlèvement.
Le mode de paiement
Un encaissement en espèces à la livraison porte des frais propres : ils apparaissent dans la décomposition rendue par le devis. Voir Paiement.
Lire la décomposition
Le devis rend le total et son détail : ce que paie le client, ce qui revient au livreur, ce que prend la plateforme. Affichez le total ; gardez le détail pour votre comptabilité, pas pour l'écran du client.
Rappel : tous les montants sont en XOF sans sous-unité. 2500 vaut deux mille cinq cents francs.