Rapidy Développeurs

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é.

Le devis dans le parcours complet
# 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.