
Logistica per marketplace in Italia: spedizioni, tracking e resi
La logistica è dove la maggior parte dei marketplace perde la battaglia dell'esperienza cliente. Il prodotto era ottimo, il pagamento era fluido, ma la spedizione ha impiegato il doppio del previsto, il codice di tracciamento non funzionava e il reso si è trasformato in un incubo di email senza risposta. Non è colpa esclusiva del corriere — è il risultato di un'integrazione mal fatta, con SLA mal definiti e processi di eccezione inesistenti.
La buona notizia è che l'ecosistema logistico italiano è maturato negli ultimi anni. Oggi esistono aggregatori di spedizioni maturi, API di tracciamento affidabili e soluzioni di logistica inversa che possono essere integrate in settimane. Il segreto è capire i livelli del problema prima di scegliere gli strumenti.
Sendcloud e Shippo: Cotazione Multi-corriere
Integrare ogni corriere individualmente è una scelta che costerà cara in manutenzione. Ogni carrier ha la propria API con comportamenti non documentati, variazioni di schema senza preavviso e rate limit diversi. Per la maggior parte dei marketplace, la soluzione corretta è usare un aggregatore di spedizioni che astragga queste differenze.
Sendcloud è il principale aggregatore per il mercato europeo, con forte presenza in Italia. Connette Poste Italiane, BRT/GLS, SDA, DHL, UPS, TNT e altri in un'unica API. La cotazione restituisce più opzioni ordinate per prezzo e tempi di consegna.
async function calculateMarketplaceShippingRates(
sellerAddress: Address,
buyerAddress: Address,
parcel: ParcelDimensions
): Promise<ShippingRate[]> {
const response = await fetch('https://panel.sendcloud.sc/api/v2/shipping-methods', {
headers: {
Authorization: `Basic ${Buffer.from(`${process.env.SENDCLOUD_KEY}:${process.env.SENDCLOUD_SECRET}`).toString('base64')}`,
},
});
const data = await response.json();
const weightKg = parcel.weightGrams / 1000;
return data.shipping_methods
.filter((method: any) =>
weightKg >= method.min_weight &&
weightKg <= method.max_weight &&
method.countries.some((c: any) => c.iso_2 === buyerAddress.countryCode)
)
.map((method: any) => ({
methodId: method.id,
carrierId: method.carrier,
serviceName: method.name,
priceEuros: parseFloat(method.price),
deliveryDays: Math.ceil(method.lead_time_hours / 24),
carrierLogo: method.carrier_image,
}))
.sort((a: ShippingRate, b: ShippingRate) => a.priceEuros - b.priceEuros);
}
La differenza di costo tra corrieri per la stessa tratta può essere rilevante — BRT può essere del 30-40% più economico di Poste Italiane per le spedizioni nel Nord Italia, mentre Poste rimane la scelta più conveniente per le consegne nel Sud e nelle isole.
Tracciamento Unificato: Astrazione per Corriere
Il tracciamento è dove l'esperienza del cliente soffre di più nelle integrazioni logistiche mal fatte. Ogni corriere ha i propri formati di stato, i propri webhook (quando li offrono) e i propri ritardi di aggiornamento.
La soluzione è un livello di astrazione che normalizza gli stati di tutti i corrieri in un modello unico:
| Status interno | Descrizione | Status BRT | Status Poste IT |
|---|---|---|---|
label_created | Etichetta generata | IN PREPARAZIONE | Presa in carico |
in_transit | In transito | IN TRANSITO | In lavorazione |
out_for_delivery | Uscito per consegna | IN CONSEGNA | In consegna |
delivered | Consegnato | CONSEGNATO | Consegnato |
failed_delivery | Tentativo fallito | NON CONSEGNATO | Tentativo non eseguito |
returned | Reso al mittente | RESO MITTENTE | Reso al mittente |
function normalizeTrackingStatus(
carrier: 'brt' | 'poste' | 'sda' | 'dhl',
rawStatus: string
): TrackingStatus {
const statusMaps: Record<string, Record<string, TrackingStatus>> = {
brt: {
'IN PREPARAZIONE': 'label_created',
'IN TRANSITO': 'in_transit',
'IN CONSEGNA': 'out_for_delivery',
'CONSEGNATO': 'delivered',
'NON CONSEGNATO': 'failed_delivery',
'RESO MITTENTE': 'returned',
},
poste: {
'Presa in carico': 'label_created',
'In lavorazione': 'in_transit',
'In consegna': 'out_for_delivery',
'Consegnato': 'delivered',
'Tentativo non eseguito': 'failed_delivery',
},
sda: {
'ACCETTATO': 'label_created',
'IN VIAGGIO': 'in_transit',
'IN CONSEGNA': 'out_for_delivery',
'CONSEGNATO': 'delivered',
},
dhl: {
'transit': 'in_transit',
'out_for_delivery': 'out_for_delivery',
'delivered': 'delivered',
'delivery_failure': 'failed_delivery',
},
};
return statusMaps[carrier]?.[rawStatus] ?? 'unknown';
}
Per i corrieri che non offrono webhook (Poste Italiane in particolare), implementate polling periodico con frequenza proporzionale all'urgenza: ogni 4 ore per spedizioni in lavorazione, ogni ora per spedizioni "in consegna".
Resi e Logistica Inversa: Il Processo Dimenticato
La logistica inversa è la parte più trascurata nella maggior parte dei progetti marketplace. I team concentrano il 90% dell'energia sul flusso in uscita (vendita → consegna) e trattano i resi come un processo manuale da risolvere "dopo".
Il risultato è prevedibile: quando il volume cresce, il team operativo si trova sommerso di resi senza processo, i clienti rimangono senza risposta e l'indice di contestazioni esplode.
Un processo minimo viable di reso in Italia (rispettando il Codice del Consumo e la Direttiva Europea 2011/83/UE) ha quattro fasi:
Richiesta: il compratore apre una richiesta di reso entro il termine previsto (14 giorni per recesso di diritto, 24 mesi per difetto di conformità). La piattaforma raccoglie il motivo, le foto del prodotto se applicabile e verifica la validità della richiesta.
Approvazione: il venditore (o la piattaforma, in base al motivo) approva o contesta. Per recesso entro 14 giorni, l'approvazione è automatica — il Codice del Consumo non lascia scelta. Per difetti, può esserci un'analisi.
Ritiro/Restituzione: generazione automatica dell'etichetta di reso. Sendcloud offre API per la creazione di etichette di logistica inversa. Il compratore riceve il codice etichetta via email e può consegnare il pacco al punto di ritiro del corriere.
async function createReturnLabel(
originalShipmentId: string,
returnReason: string
): Promise<ReturnLabelResult> {
const response = await fetch('https://panel.sendcloud.sc/api/v2/returns', {
method: 'POST',
headers: {
Authorization: `Basic ${Buffer.from(`${process.env.SENDCLOUD_KEY}:${process.env.SENDCLOUD_SECRET}`).toString('base64')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
collo_nr: originalShipmentId,
reason: returnReason,
from_address_id: 1, // ID dell'indirizzo del venditore
}),
});
const data = await response.json();
return {
returnId: data.id,
labelUrl: data.label_url,
trackingCode: data.tracking_number,
};
}
Rimborso: dopo la conferma di ricezione del prodotto da parte del venditore (o dopo il termine per la contestazione), il rimborso viene elaborato automaticamente. Questo deve essere automatizzato — elaborare rimborsi manualmente non è scalabile.
Conclusione
La logistica ben implementata è un vantaggio competitivo che la maggior parte dei marketplace sottovaluta. Gli acquirenti che hanno avuto una buona esperienza di consegna — tracciamento chiaro, tempi rispettati, reso senza burocrazia — tornano. Chi ha avuto un'esperienza negativa non torna e lo racconta ad altri.
Integrare i corrieri correttamente richiede decisioni architetturali che impattano il modello di dati, i flussi di notifica, la struttura dei costi e l'esperienza del venditore. Queste decisioni sono molto più facili da prendere prima dello sviluppo che da correggere dopo.
Nella SystemForge documentiamo tutti questi flussi in modo strutturato — dal modello di dati delle spedizioni ai webhook di tracciamento e ai flussi di reso — creando la base tecnica che il team di sviluppo ha bisogno per costruire l'integrazione logistica correttamente al primo tentativo. Contatta il nostro team.
Hai bisogno di aiuto?