Sendcloud
Sendcloud : plateforme shipping européenne avec 80+ transporteurs integration. Solution complète checkout, tracking et returns management.
📚 Ressources Complémentaires
📖 Guides Pratiques
⚖️ Comparatifs
Sendcloud : Shipping Européen Unifié
Qu’est-ce que Sendcloud ?
Sendcloud est la plateforme shipping européenne utilisée par 25k+ e-commerces dont Coolblue, About You, Rituals. Cette scale-up Amsterdam-based unifie 80+ transporteurs européens avec checkout shipping, branded tracking, returns automation et APIs developer-friendly pour PME et enterprises Europe-focused.
🚀 Fonctionnalités Principales
Multi-Carrier European Network
- 80+ carriers : DPD, DHL, UPS, Colissimo, GLS, Hermes
- Local expertise : carriers spécialisés par pays
- Service levels : standard, express, same-day options
- Coverage : 27 pays européens comprehensive
Checkout Shipping Integration
- Real-time rates : API shipping calculator
- Delivery options : pickup points, home delivery
- Date selection : customer preferred delivery
- Mobile optimized : responsive checkout experience
Returns Management
- Self-service portal : customers initiate returns
- QR code labels : smartphone-generated returns
- Automated processing : return status tracking
- Refund triggers : integration e-commerce platforms
Branded Experience
- Custom tracking : white-label pages branded
- Email notifications : automated customer updates
- SMS alerts : delivery notifications real-time
- Customer portal : shipment management self-service
💰 Prix et Structure
Free Plan
- 25 shipments/month : ideal small businesses testing
- Basic integrations : Shopify, WooCommerce core
- Standard support : email community forum
- Core features : rate comparison, basic tracking
Essential Plan : €25/mois
- 250 shipments/month : growing e-commerce needs
- All integrations : 50+ platforms access
- Phone support : business hours assistance
- Advanced features : branded tracking, returns
Professional Plan : €65/mois
- 1000 shipments/month : scale business operations
- Priority support : dedicated account manager
- Advanced analytics : performance insights detailed
- Custom integrations : API development support
Enterprise Plan : Custom
- Unlimited shipments : volume pricing negotiation
- SLA guarantees : 99.9% uptime commitment
- Account management : strategic partnership
- Custom development : bespoke features development
⭐ Points Forts
🇪🇺 European Expertise
Local knowledge :
- 80+ carriers European partnerships
- Country-specific regulations compliance
- Local customer preferences understanding
- Cross-border VAT handling automatic
🛒 Checkout Experience
Conversion optimization :
- Real-time shipping rates calculation
- Pickup point selection interactive maps
- Delivery date preferences customer choice
- Mobile-first responsive design
📱 Customer Experience
Branded journey :
- White-label tracking pages custom
- Automated notifications multi-channel
- Self-service returns portal
- Customer satisfaction surveys integrated
🔧 Integration Simplicity
Developer-friendly :
- APIs RESTful well-documented
- Webhooks real-time notifications
- SDKs multiple languages available
- Plugin marketplace extensive
⚠️ Points Faibles
💰 Pricing Escalation
Cost structure challenges :
- Per-shipment fees accumulate quickly
- Volume thresholds jump significantly
- Limited free tier usage
- Premium features expensive
🌍 Geographic Limitations
European focus restrictions :
- Limited global coverage
- North America/Asia partnerships weak
- International shipping options fewer
- Customs handling basic
📊 Feature Limitations
Tier restrictions :
- Advanced analytics premium only
- API rate limits free/basic plans
- Custom branding higher tiers
- Integrations limited lower plans
📞 Support Tiers
Customer service gaps :
- Free plan email support only
- Response times tier-dependent
- Phone support business hours only
- Technical documentation basic
🎯 Pour Qui ?
✅ Parfait Pour
- E-commerces européens domestic/intra-EU focus
- Fashion retailers returns-heavy categories
- SME growth 100-1000 shipments/month
- Multi-country expansion European markets
- Customer experience priority businesses
❌ Moins Adapté Pour
- Global shippers worldwide coverage needs
- High-volume >5000 shipments/month cost
- B2B logistics complex enterprise needs
- US-focused businesses North America
- Low-margin products tight budgets
📊 Sendcloud vs European Shipping Platforms
| Critère | Sendcloud | Easyship | ShipStation |
|---|---|---|---|
| European Focus | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| Carrier Network | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Checkout Integration | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| Returns Management | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| Pricing Value | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
🛠️ Configuration & Intégration
Sendcloud API Integration
// Sendcloud API integration
const axios = require('axios');
class SendcloudService {
constructor(publicKey, secretKey, environment = 'live') {
this.publicKey = publicKey;
this.secretKey = secretKey;
this.baseURL = environment === 'live'
? 'https://panel.sendcloud.sc/api/v2'
: 'https://panel.sendcloud.sc/api/v2';
this.auth = Buffer.from(`${publicKey}:${secretKey}`).toString('base64');
}
async getShippingMethods(senderAddress, recipientAddress, parcel) {
try {
const response = await axios.post(`${this.baseURL}/shipping-methods`, {
sender_address: {
company_name: senderAddress.company,
contact_name: senderAddress.name,
address: senderAddress.street,
address_2: senderAddress.street2,
house_number: senderAddress.houseNumber,
city: senderAddress.city,
postal_code: senderAddress.postalCode,
country: senderAddress.country,
telephone: senderAddress.phone,
email: senderAddress.email
},
to_address: {
company_name: recipientAddress.company,
contact_name: recipientAddress.name,
address: recipientAddress.street,
address_2: recipientAddress.street2,
house_number: recipientAddress.houseNumber,
city: recipientAddress.city,
postal_code: recipientAddress.postalCode,
country: recipientAddress.country,
telephone: recipientAddress.phone,
email: recipientAddress.email
},
parcel: {
name: parcel.name,
weight: Math.round(parcel.weight * 1000), // Convert kg to grams
length: parcel.dimensions.length,
width: parcel.dimensions.width,
height: parcel.dimensions.height,
value: parcel.value,
currency: parcel.currency || 'EUR'
},
request_label: false
}, {
headers: {
'Authorization': `Basic ${this.auth}`,
'Content-Type': 'application/json'
}
});
return response.data.shipping_methods.map(method => ({
id: method.id,
name: method.name,
carrier: method.carrier,
service_point_input: method.service_point_input,
price: parseFloat(method.price),
currency: method.currency,
min_delivery_date: method.min_delivery_date,
max_delivery_date: method.max_delivery_date,
countries: method.countries
}));
} catch (error) {
console.error('Shipping methods request failed:', error.response?.data || error.message);
throw new Error('Unable to get shipping methods');
}
}
async createParcel(parcelData) {
try {
const response = await axios.post(`${this.baseURL}/parcels`, {
name: parcelData.customerName,
company_name: parcelData.customerCompany || '',
address: parcelData.address.street,
address_2: parcelData.address.street2 || '',
house_number: parcelData.address.houseNumber,
city: parcelData.address.city,
postal_code: parcelData.address.postalCode,
country: parcelData.address.country,
telephone: parcelData.address.phone || '',
email: parcelData.address.email,
data: parcelData.customData || {},
to_service_point: parcelData.servicePointId || null,
shipping_method: parcelData.shippingMethodId,
weight: Math.round(parcelData.weight * 1000), // Convert to grams
length: parcelData.dimensions?.length || 10,
width: parcelData.dimensions?.width || 10,
height: parcelData.dimensions?.height || 10,
request_label: true,
apply_shipping_rules: true
}, {
headers: {
'Authorization': `Basic ${this.auth}`,
'Content-Type': 'application/json'
}
});
const parcel = response.data.parcel;
return {
id: parcel.id,
name: parcel.name,
address: parcel.address,
trackingNumber: parcel.tracking_number,
trackingUrl: parcel.tracking_url,
labelUrl: parcel.label?.label_printer || parcel.label?.normal_printer?.[0],
carrier: parcel.carrier?.code,
status: parcel.status?.message,
shippingMethod: parcel.shipment?.name
};
} catch (error) {
console.error('Parcel creation failed:', error.response?.data || error.message);
throw new Error('Failed to create parcel');
}
}
async getServicePoints(country, carrier, postalCode, city) {
try {
const response = await axios.get(`${this.baseURL}/service-points`, {
params: {
country: country,
carrier: carrier,
postal_code: postalCode,
city: city,
radius: 5000 // 5km radius
},
headers: {
'Authorization': `Basic ${this.auth}`
}
});
return response.data.map(point => ({
id: point.id,
name: point.name,
street: point.street,
houseNumber: point.house_number,
postalCode: point.postal_code,
city: point.city,
country: point.country,
phone: point.phone,
email: point.email,
openingHours: point.opening_hours,
distance: point.distance,
latitude: parseFloat(point.latitude),
longitude: parseFloat(point.longitude)
}));
} catch (error) {
console.error('Service points request failed:', error.response?.data || error.message);
throw new Error('Unable to get service points');
}
}
async trackParcel(parcelId) {
try {
const response = await axios.get(`${this.baseURL}/parcels/${parcelId}`, {
headers: {
'Authorization': `Basic ${this.auth}`
}
});
const parcel = response.data.parcel;
return {
id: parcel.id,
trackingNumber: parcel.tracking_number,
trackingUrl: parcel.tracking_url,
status: {
id: parcel.status.id,
message: parcel.status.message,
timestamp: parcel.date_created
},
carrier: parcel.carrier,
address: parcel.address,
events: parcel.tracking_events || []
};
} catch (error) {
console.error('Parcel tracking failed:', error.response?.data || error.message);
throw new Error('Unable to track parcel');
}
}
async createReturn(originalParcelId, returnData) {
try {
const response = await axios.post(`${this.baseURL}/returns`, {
parcel: originalParcelId,
message: returnData.reason || '',
return_label: true,
refund: returnData.refundRequested || false,
return_portal: returnData.useReturnPortal || true
}, {
headers: {
'Authorization': `Basic ${this.auth}`,
'Content-Type': 'application/json'
}
});
const returnInfo = response.data.return;
return {
id: returnInfo.id,
trackingNumber: returnInfo.tracking_number,
trackingUrl: returnInfo.tracking_url,
labelUrl: returnInfo.label_url,
status: returnInfo.status,
returnPortalUrl: returnInfo.return_portal_url
};
} catch (error) {
console.error('Return creation failed:', error.response?.data || error.message);
throw new Error('Failed to create return');
}
}
async handleWebhook(eventType, data) {
console.log(`Sendcloud webhook: ${eventType}`, data);
switch (eventType) {
case 'parcel_status_changed':
await this.handleParcelStatusChange(data);
break;
case 'integration_credentials':
await this.handleCredentialsUpdate(data);
break;
case 'return_created':
await this.handleReturnCreated(data);
break;
default:
console.log('Unhandled webhook event:', eventType);
}
}
async handleParcelStatusChange(data) {
const parcel = data.parcel;
console.log(`Parcel ${parcel.id} status changed to: ${parcel.status.message}`);
// Update order status in your system
// Send customer notification
// Trigger post-delivery actions (reviews, etc.)
}
}
// Usage example
const sendcloudService = new SendcloudService(
process.env.SENDCLOUD_PUBLIC_KEY,
process.env.SENDCLOUD_SECRET_KEY,
'live'
);
// Get shipping options for checkout
async function getCheckoutShippingOptions(orderData) {
try {
const shippingMethods = await sendcloudService.getShippingMethods(
{
company: 'Your Store',
name: 'Store Manager',
street: 'Business Street 123',
houseNumber: '123',
city: 'Amsterdam',
postalCode: '1012AB',
country: 'NL',
phone: '+31123456789',
email: 'store@yourstore.com'
},
{
name: orderData.customer.name,
company: orderData.customer.company,
street: orderData.shipping.street,
houseNumber: orderData.shipping.houseNumber,
city: orderData.shipping.city,
postalCode: orderData.shipping.postalCode,
country: orderData.shipping.country,
phone: orderData.customer.phone,
email: orderData.customer.email
},
{
name: 'Order Package',
weight: orderData.totalWeight, // in kg
dimensions: orderData.dimensions,
value: orderData.totalValue,
currency: 'EUR'
}
);
return shippingMethods;
} catch (error) {
console.error('Failed to get shipping options:', error);
return [];
}
}
Shopify Integration
// Sendcloud Shopify integration
class SendcloudShopifyIntegration {
constructor(sendcloudService) {
this.sendcloud = sendcloudService;
}
async processShopifyOrder(order) {
try {
// Convert Shopify order to Sendcloud format
const parcelData = {
customerName: `${order.shipping_address.first_name} ${order.shipping_address.last_name}`,
customerCompany: order.shipping_address.company,
address: {
street: order.shipping_address.address1,
street2: order.shipping_address.address2,
houseNumber: this.extractHouseNumber(order.shipping_address.address1),
city: order.shipping_address.city,
postalCode: order.shipping_address.zip,
country: order.shipping_address.country_code,
phone: order.shipping_address.phone,
email: order.email
},
weight: this.calculateTotalWeight(order.line_items),
dimensions: this.estimatePackageDimensions(order.line_items),
shippingMethodId: this.mapShopifyToSendcloud(order.shipping_lines[0]),
customData: {
shopify_order_id: order.id,
order_number: order.order_number,
total_price: order.total_price,
currency: order.currency
}
};
const parcel = await this.sendcloud.createParcel(parcelData);
// Update Shopify order with tracking information
await this.updateShopifyTracking(order.id, parcel);
return parcel;
} catch (error) {
console.error('Shopify order processing failed:', error);
throw error;
}
}
extractHouseNumber(address) {
// Simple regex to extract house number from address
const match = address.match(/(\d+)/);
return match ? match[1] : '';
}
calculateTotalWeight(lineItems) {
return lineItems.reduce((total, item) => {
return total + ((item.grams || 0) * item.quantity / 1000); // Convert to kg
}, 0.5); // Minimum 0.5kg
}
estimatePackageDimensions(lineItems) {
// Simple box estimation - in production, use actual product dimensions
return {
length: 30,
width: 20,
height: 10
};
}
mapShopifyToSendcloud(shippingLine) {
// Map Shopify shipping method to Sendcloud shipping method ID
// This would be configured in your system
const mappings = {
'Standard Shipping': 1,
'Express Shipping': 2,
'DPD Home': 3,
'PostNL': 4
};
return mappings[shippingLine?.title] || 1; // Default to standard
}
async updateShopifyTracking(orderId, parcel) {
// Update Shopify order with tracking information
// This would use Shopify Admin API
console.log(`Updating Shopify order ${orderId} with tracking ${parcel.trackingNumber}`);
// Example Shopify API call (simplified)
/*
await shopify.order.createFulfillment(orderId, {
tracking_number: parcel.trackingNumber,
tracking_url: parcel.trackingUrl,
tracking_company: parcel.carrier
});
*/
}
}
🏆 Notre Verdict
Sendcloud excellent choix e-commerces européens cherchant solution shipping complète avec focus customer experience et returns management. Pricing competitive pour volumes modérés.
Note Globale : 4.2/5 ⭐⭐⭐⭐⭐
- European Coverage : 5/5
- Checkout Integration : 5/5
- Returns Management : 5/5
- Pricing Value : 3/5
- Global Reach : 2/5
🎯 Cas d’Usage Réels
💡 Exemple : Fashion E-commerce Multi-pays
European expansion :
- Local carriers : DPD Germany, Colissimo France, Royal Mail UK
- Pickup points : 50k+ locations customer convenience
- Returns automation : 25% return rate fashion handled
- Branded experience : white-label tracking pages
💡 Exemple : Electronics Retailer
Customer satisfaction focus :
- Delivery options : home/pickup point choice
- Real-time tracking : proactive notifications
- Easy returns : QR code generation smartphone
- Multi-language : localized customer experience
💡 Conseil OSCLOAD : Sendcloud optimal choice e-commerces européens prioritizing customer experience et operational simplicity. Scale pricing carefully. Alternative Easyship global needs ou ShipStation US-focus.