Shipping Costs
Shipping Costs Guide
This guide explains how to calculate shipping costs for outbound orders using the Spreetail Channel Integration API.
Overview
The shipping cost calculation endpoint allows you to:
- Get accurate shipping cost estimates
- Compare different shipping options
- Calculate costs before order creation
- Optimize shipping decisions
Note: The shipping cost endpoint requires enablement. Contact [email protected] to enable this feature for your account. The endpoint requires
EnabledEndpoints.outbound_cost = truein your client configuration.
Endpoint
POST /outbound-cost
Full URL: https://api.spreetaileu.com/api/api/v1/outbound-cost
Authentication
Important: This endpoint uses API Key authentication, not Bearer token authentication. Use your Client ID and Client Secret in the format:
ApiKey CLIENT_ID:CLIENT_SECRET
Include your Client ID and Client Secret in the Authorization header:
Authorization: ApiKey your-client-id:your-client-secret
Request Structure
To calculate shipping costs, provide:
- Country: Destination country code (ISO 3166-1 alpha-2, e.g., "DE", "GB", "US")
- Items: Array of items, each with:
sku(string): Product SKU identifierweight(number): Item weight in kilograms (minimum: 0.01, maximum: 10000)length(number): Item length in centimeters (minimum: 0.01, maximum: 10000)width(number): Item width in centimeters (minimum: 0.01, maximum: 10000)height(number): Item height in centimeters (minimum: 0.01, maximum: 10000)
Required Fields
| Field | Type | Description |
|---|---|---|
country | string | Destination country code (ISO 3166-1 alpha-2, exactly 2 characters) |
items | array | Array of items to ship (minimum 1 item required) |
items[].sku | string | Product SKU identifier |
items[].weight | number | Item weight in kilograms (0.01 - 10000) |
items[].length | number | Item length in centimeters (0.01 - 10000) |
items[].width | number | Item width in centimeters (0.01 - 10000) |
items[].height | number | Item height in centimeters (0.01 - 10000) |
Example Request: Single Item
{
"country": "DE",
"items": [
{
"sku": "PROD-12345",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10
}
]
}Example Request: Multiple Items
{
"country": "GB",
"items": [
{
"sku": "PROD-12345",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10
},
{
"sku": "PROD-67890",
"weight": 1.2,
"length": 15,
"width": 10,
"height": 5
}
]
}Code Examples
Python
import requests
def calculate_shipping_cost(client_id, client_secret, cost_data):
"""Calculate shipping cost for an order"""
url = "https://api.spreetaileu.com/api/api/v1/outbound-cost"
headers = {
"Authorization": f"ApiKey {client_id}:{client_secret}",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, json=cost_data)
response.raise_for_status()
return response.json()
# Example usage
cost_request = {
"country": "DE",
"items": [
{
"sku": "PROD-12345",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10
}
]
}
result = calculate_shipping_cost("your-client-id", "your-client-secret", cost_request)
# Display eligible carriers
if result['success']:
print("Available shipping options:")
for carrier in result['data']['eligible_carriers']:
print(f" {carrier['carrier_name']} ({carrier['service_name']}): "
f"{carrier['cost']} {carrier['currency']} - "
f"{carrier['estimated_delivery_days']} days")
# Display rejected carriers if any
if result['data']['rejected_carriers']:
print("\nUnavailable carriers:")
for carrier in result['data']['rejected_carriers']:
print(f" {carrier['carrier_name']}: {carrier['reason']}")JavaScript/Node.js
async function calculateShippingCost(clientId, clientSecret, costData) {
const url = 'https://api.spreetaileu.com/api/api/v1/outbound-cost';
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `ApiKey ${clientId}:${clientSecret}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(costData)
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Shipping cost calculation failed: ${error.error || response.statusText}`);
}
return await response.json();
}
// Example usage
const costRequest = {
country: 'DE',
items: [
{
sku: 'PROD-12345',
weight: 2.5,
length: 20,
width: 15,
height: 10
}
]
};
calculateShippingCost('your-client-id', 'your-client-secret', costRequest)
.then(result => {
if (result.success) {
console.log('Available shipping options:');
result.data.eligible_carriers.forEach(carrier => {
console.log(
`${carrier.carrier_name} (${carrier.service_name}): ` +
`${carrier.cost} ${carrier.currency} - ` +
`${carrier.estimated_delivery_days} days`
);
});
if (result.data.rejected_carriers.length > 0) {
console.log('\nUnavailable carriers:');
result.data.rejected_carriers.forEach(carrier => {
console.log(`${carrier.carrier_name}: ${carrier.reason}`);
});
}
}
})
.catch(error => console.error('Error:', error));Response Format
Success Response (200)
{
"success": true,
"data": {
"eligible_carriers": [
{
"carrier_name": "DHL",
"service_name": "Express",
"cost": 12.5,
"currency": "EUR",
"estimated_delivery_days": 2,
"tracking_available": true
},
{
"carrier_name": "DPD",
"service_name": "Standard",
"cost": 8.75,
"currency": "EUR",
"estimated_delivery_days": 5,
"tracking_available": true
}
],
"rejected_carriers": [
{
"carrier_name": "Royal Mail",
"reason": "Destination not supported"
}
]
}
}Response Fields
| Field | Type | Description |
|---|---|---|
eligible_carriers | array | Array of carriers that can fulfill the shipment |
eligible_carriers[].carrier_name | string | Name of the shipping carrier |
eligible_carriers[].service_name | string | Service level name |
eligible_carriers[].cost | number | Shipping cost |
eligible_carriers[].currency | string | Currency code (ISO 4217) |
eligible_carriers[].estimated_delivery_days | integer | Estimated delivery time in days |
eligible_carriers[].tracking_available | boolean | Whether tracking is available |
rejected_carriers | array | Array of carriers that cannot fulfill the shipment |
rejected_carriers[].carrier_name | string | Name of the shipping carrier |
rejected_carriers[].reason | string | Reason for rejection |
Use Cases
1. Compare Shipping Options
def compare_shipping_options(client_id, client_secret, country, items):
"""Compare different shipping options for a shipment"""
cost_request = {
"country": country,
"items": items
}
result = calculate_shipping_cost(client_id, client_secret, cost_request)
if result['success']:
eligible = result['data']['eligible_carriers']
# Sort by cost
sorted_by_cost = sorted(eligible, key=lambda x: x['cost'])
# Sort by delivery time
sorted_by_time = sorted(eligible, key=lambda x: x['estimated_delivery_days'])
return {
"cheapest": sorted_by_cost[0] if sorted_by_cost else None,
"fastest": sorted_by_time[0] if sorted_by_time else None,
"all_options": eligible
}
return None
# Usage
items = [
{
"sku": "PROD-12345",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10
}
]
options = compare_shipping_options("client-id", "client-secret", "DE", items)
if options:
print(f"Cheapest: {options['cheapest']['carrier_name']} - {options['cheapest']['cost']} EUR")
print(f"Fastest: {options['fastest']['carrier_name']} - {options['fastest']['estimated_delivery_days']} days")2. Validate Shipping Feasibility
def check_shipping_feasibility(client_id, client_secret, country, items):
"""Check if shipping is possible to a destination"""
cost_request = {
"country": country,
"items": items
}
result = calculate_shipping_cost(client_id, client_secret, cost_request)
if result['success']:
eligible_count = len(result['data']['eligible_carriers'])
rejected_count = len(result['data']['rejected_carriers'])
return {
"feasible": eligible_count > 0,
"eligible_carriers": eligible_count,
"rejected_carriers": rejected_count,
"options": result['data']['eligible_carriers']
}
return {"feasible": False, "error": "Calculation failed"}
# Usage
feasibility = check_shipping_feasibility("client-id", "client-secret", "DE", items)
if feasibility['feasible']:
print(f"Shipping available via {feasibility['eligible_carriers']} carrier(s)")
else:
print("Shipping not available to this destination")Important Notes
Endpoint Enablement
- This endpoint requires special enablement
- Contact [email protected] to enable
- Not all accounts have access by default
- The endpoint requires
EnabledEndpoints.outbound_cost = truein your client configuration
Authentication
- Uses API Key authentication, not Bearer token
- Format:
Authorization: ApiKey CLIENT_ID:CLIENT_SECRET - Do not use JWT tokens for this endpoint
Country Code
- Must be a valid ISO 3166-1 alpha-2 country code
- Exactly 2 characters (e.g., "DE", "GB", "US")
- Case-sensitive (use uppercase)
Weight and Dimensions
- Weight: Must be in kilograms (minimum: 0.01, maximum: 10000)
- Dimensions: Must be in centimeters (minimum: 0.01, maximum: 10000)
- All dimensions are required for each item
- Providing accurate measurements improves cost calculation accuracy
Items Array
- At least one item is required
- Each item must include all required fields:
sku,weight,length,width,height - Multiple items in one request represent a combined shipment
Error Handling
Endpoint Not Enabled (403)
If the endpoint is not enabled for your account:
{
"success": false,
"error": "Forbidden - outbound-cost endpoint not enabled for this client"
}Solution: Contact [email protected] to enable the feature.
Invalid Request (400)
{
"success": false,
"error": "Invalid request (missing fields, invalid values)"
}Solution: Verify all required fields are present and values are within valid ranges.
Authentication Error (401)
{
"success": false,
"error": "Unauthorized"
}Solution: Verify your Client ID and Client Secret are correct and use the ApiKey format.
Best Practices
- Calculate Before Order Creation: Get shipping costs before finalizing orders
- Cache Results: Cache shipping costs for similar destinations/items
- Handle Errors: Implement fallback for when endpoint is unavailable
- Compare Options: Use the response to compare multiple carrier options
- Consider Delivery Time: Factor in estimated delivery days when selecting carriers
- Validate Dimensions: Ensure weight and dimensions are accurate for better cost estimates
Related Endpoints
POST /outbound- Create order (use shipping cost information in order)GET /order/{referenceNumber}- Check order status and actual shipping details
Updated 5 days ago
