Skip to main content

Understanding Scope 3 Category 9

Downstream transportation and distribution covers emissions from transporting and distributing products sold by your organization—in vehicles and facilities not owned or controlled by you, when the customer arranges and pays for transportation. According to the GHG Protocol Scope 3 Standard, Category 9 includes:
  • Outbound logistics (customer-paid): Transportation of sold goods from your facilities to customers, when the customer pays
  • Third-party distribution: Distribution services arranged by customers or retailers
  • Retail distribution: Movement from your distribution centers to retail stores (if retailer pays)
┌─────────────────────────────────────────────────────────────────────────────┐
│              SCOPE 3 CATEGORY 9: Downstream Transportation                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  YOUR OPERATIONS                              YOUR CUSTOMERS (DOWNSTREAM)   │
│  ─────────────────                            ───────────────────────────   │
│                                                                             │
│  ┌──────────────┐      ┌──────────────┐      ┌──────────────┐               │
│  │    Your      │      │  Distribution│      │   End        │               │
│  │  Facilities  │ ───► │   Centers    │ ───► │  Customers   │               │
│  │              │      │   (if any)   │      │              │               │
│  │              │      │              │      │              │               │
│  └──────────────┘      └──────────────┘      └──────────────┘               │
│         │                     │                     ▲                       │
│         │                     │                     │                       │
│         └─────────────────────┴─────────────────────┘                       │
│                                     │                                       │
│                        ┌────────────▼────────────┐                          │
│                        │      CATEGORY 9         │                          │
│                        │  Transportation of      │                          │
│                        │  sold products from     │                          │
│                        │  your organization      │                          │
│                        │  to end customers       │                          │
│                        └─────────────────────────┘                          │
│                                                                             │
│  INCLUDED IN CATEGORY 9:                                                    │
│  • Customer-arranged trucking services                                      │
│  • Retail pickup/delivery (customer-paid)                                   │
│  • Air cargo (outbound, customer-paid)                                      │
│  • Maritime shipping (exports, customer-paid)                               │
│  • Last-mile delivery (when customer pays)                                  │
│  • Third-party warehousing (customer-arranged)                              │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
Category 9 vs Category 4
  • Category 9 (Downstream): Transportation of products you sell from your facilities to customers—when the customer arranges and pays
  • Category 4 (Upstream): Transportation of products you purchase from suppliers to your facilities, OR outbound logistics services you purchase
Important: Who Pays Matters!If you (the reporting company) purchase outbound logistics services to deliver products to customers, those emissions belong in Category 4—not Category 9. Category 9 only applies when the customer arranges and pays for transportation.Examples:
  • You hire a carrier to deliver to customers → Category 4
  • Customer arranges their own pickup/delivery → Category 9
  • FOB origin (customer pays freight) → Category 9
  • DDP terms (you pay all shipping) → Category 4

Prerequisites

Before starting, ensure you have:
Using the Dcycle App?You can track downstream transportation through our web interface:
  • Upload sent goods for outbound shipments
  • Upload via CSV for bulk data

Data Map: Category 9 Requirements Overview

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                   CATEGORY 9 DATA REQUIREMENTS OVERVIEW                                  │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐   │
│  │ TRANSPORT ROUTE (Per shipment)                                                  │   │
│  ├─────────────────────────────────────────────────────────────────────────────────┤   │
│  │                                                                                 │   │
│  │  Required Fields              Optional Fields                                   │   │
│  │  ──────────────────           ──────────────────                                │   │
│  │  • start_date                 • name (shipment name)                            │   │
│  │  • end_date                   • customer (customer name)                        │   │
│  │  • quantity_transported       • refrigerated (true/false)                       │   │
│  │  • unit_id (kg or tonnes)                                                       │   │
│  │  • transport_direction                                                          │   │
│  │    ("downstream" for Cat 9)                                                     │   │
│  │                                                                                 │   │
│  └─────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐   │
│  │ TRANSPORT SECTIONS (Per leg of journey)                                         │   │
│  ├─────────────────────────────────────────────────────────────────────────────────┤   │
│  │                                                                                 │   │
│  │  Conditionally Required       Optional Fields                                   │   │
│  │  ──────────────────────       ──────────────────                                │   │
│  │  • origin (city/address)*     • travel_method (car/truck                        │   │
│  │  • destination (city/addr)*     for road transport)                             │   │
│  │  • transport_type             • electric (true/false)                           │   │
│  │    (air/road/rail/maritime/                                                     │   │
│  │     unknown)                                                                    │   │
│  │  • kms (distance)*                                                              │   │
│  │                                                                                 │   │
│  │  * See conditional requirements below                                           │   │
│  │                                                                                 │   │
│  └─────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐   │
│  │ CALCULATION FLOW                                                                │   │
│  ├─────────────────────────────────────────────────────────────────────────────────┤   │
│  │                                                                                 │   │
│  │  Origin + Destination ──► Geocoding ──► Distance (kms)                          │   │
│  │                                             │                                   │   │
│  │  transport_type + electric + refrigerated ──┼──► Emission Factor                │   │
│  │                                             │                                   │   │
│  │  Quantity (kg/t) × Distance (km) × EF ──────┴──► CO₂e (kg)                      │   │
│  │                                                                                 │   │
│  └─────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘
Unknown Transport TypeIf the transport type (vehicle) is unknown, you can set transport_type: "unknown" and Dcycle will estimate the most likely transport mode based on the origin and destination data.When using transport_type: "unknown":
  • Origin and destination are mandatory - Dcycle needs location data to estimate the appropriate transport mode
  • The system analyzes the route characteristics (distance, countries involved) to determine if it’s likely road, rail, maritime, or air transport
Distance (kms) FieldThe kms field allows you to provide the exact distance if known. This is useful when:
  • You have precise distance data from your logistics provider
  • The route is non-standard (e.g., specific highway routes)
  • Geocoding might not accurately represent the actual route
Conditional requirements:
  • If kms is provided: Origin and destination are optional (distance is already known)
  • If kms is not provided: Origin and destination are mandatory (Dcycle calculates distance via geocoding)

Calculation Methods

The most accurate method uses the Dcycle Transport and Distribution API:
┌─────────────────────────────────────────────────────────────────────────────┐
│                    DISTANCE-BASED CALCULATION FLOW                           │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  Your Data          Dcycle Processing                    Output             │
│  ─────────────      ──────────────────                   ──────             │
│                                                                              │
│  ┌─────────────┐    ┌─────────────────┐    ┌──────────┐    ┌─────────────┐  │
│  │ Origin:     │    │ Geocoding:      │    │ Distance │    │ CO₂e (kg):  │  │
│  │ "Barcelona, │ ─► │ Lat/Lng lookup  │ ─► │ ~1,200   │ ─► │ 185 kg      │  │
│  │  Spain"     │    │                 │    │ km       │    │             │  │
│  └─────────────┘    └─────────────────┘    └──────────┘    └─────────────┘  │
│                                                     │                       │
│  ┌─────────────┐    ┌─────────────────┐             │                       │
│  │ Destination:│    │ Transport type: │             │                       │
│  │ "Paris,     │ ─► │ road            │ ────────────┤                       │
│  │  France"    │    │                 │             │                       │
│  └─────────────┘    └─────────────────┘             │                       │
│                                                     │                       │
│  ┌─────────────┐    ┌─────────────────┐             │                       │
│  │ Weight:     │    │ Emission Factor │             │                       │
│  │ 2,000 kg    │ ─► │ based on type,  │ ────────────┘                       │
│  │             │    │ electric, refrig│                                     │
│  └─────────────┘    └─────────────────┘                                     │
│                                                                              │
│  Formula: CO₂e = Quantity × Distance (km) × Emission Factor                 │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
Dcycle supports four transport types:
Transport TypeDescriptionUse Case
airAir freightExpress international, high-value goods
roadRoad transportRegional/national freight
railRail freightBulk goods, continental routes
maritimeSea freightInternational shipping, containers
For road transport, you can further specify the travel_method:
  • truck - Heavy goods vehicles (default for freight)
  • car - Light vehicles
  • bicycle - Zero emission (non-electric)
  • electric_kick_scooter - Last-mile delivery
  • motorbike - Small deliveries
Emission factors are adjusted based on:Electric vehicles:
  • Set electric: true for electric vehicles
  • Significantly lower emissions for road and rail
Refrigerated transport:
  • Set refrigerated: true for cold chain logistics
  • Adds ~10-20% to emissions due to cooling energy
Aircraft size (for air transport):
  • Automatically determined by distance
  • Short-haul vs long-haul aircraft have different factors
For transport and distribution, Dcycle uses emission factors from:Ecoinvent:
  • Comprehensive lifecycle emission factors by transport mode
  • Covers road, rail, air, and maritime transport
  • Accounts for vehicle type, fuel, and regional variations
  • Updated regularly with latest LCA data
Distance calculation:
  • Road/Rail/Air: Google Maps API for accurate routing
  • Maritime: CERDI distance databases

Step 1: Calculate Shipment Emissions

Transport Route fields:
FieldTypeRequiredDescriptionExample
quantity_transportednumberCargo weight2000
unit_idUUIDUnit (kg or metric_tonne)"kg-unit-uuid"
start_datedateStart of transport period"2024-01-15"
end_datedateEnd of transport period"2024-01-16"
transport_directionstringDirection"downstream"
customerstringCustomer name"Customer A"
refrigeratedbooleanCold chain transportfalse
Transport Section fields:
FieldTypeRequiredDescriptionExample
originstring⚠️Your facility location"Barcelona, Spain"
destinationstring⚠️Customer location"Paris, France"
transport_typestringMode of transport"road" or "unknown"
kmsnumber⚠️Distance in kilometers1050
travel_methodstringVehicle type (for road)"truck"
electricbooleanElectric vehiclefalse
⚠️ Conditional requirements:
  • If kms is provided → origin and destination are optional
  • If kms is NOT provided → origin and destination are required
  • If transport_type is "unknown"origin and destination are required
Where to get this data:
  • Origin: Your warehouse/facility address
  • Destination: Customer shipping address from sales orders
  • Weight: Packing list, sales order, or shipping manifest
  • Transport type: Carrier information or customer pickup method
  • Kms: Distance from logistics provider or shipping invoice
Track individual outbound shipments to customers:
import requests
import os

headers = {
    "Authorization": f"Bearer {os.getenv('DCYCLE_API_KEY')}",
    "Content-Type": "application/json",
    "x-organization-id": os.getenv("DCYCLE_ORG_ID"),
    "x-user-id": os.getenv("DCYCLE_USER_ID"),
}

# Get unit IDs
units = requests.get(
    "https://api.dcycle.io/api/v1/units",
    headers=headers,
    params={"page": 1, "size": 100}
).json()
kg_unit = next(u for u in units['items'] if u['abbreviation'] == 'kg')

# Example: Road freight to customer (customer-arranged)
# Step 1: Create transport route
transport_route = {
    "start_date": "2024-01-15",
    "end_date": "2024-01-16",
    "quantity_transported": 2000,  # 2 tonnes
    "unit_id": kg_unit['id'],
    "transport_direction": "downstream",  # Category 9
    "customer": "Customer A - Paris",
    "refrigerated": False,
}

route_response = requests.post(
    "https://api.dcycle.io/api/v1/transport_routes",
    headers=headers,
    json=transport_route
).json()

# Step 2: Create transport section (leg of journey)
transport_section = {
    "transport_route_id": route_response['id'],
    "origin": "Barcelona, Spain",
    "destination": "Paris, France",
    "transport_type": "road",
    "travel_method": "truck",
    "electric": False,
}

section_response = requests.post(
    "https://api.dcycle.io/api/v1/transport_sections",
    headers=headers,
    json=transport_section
).json()

print(f"✅ Outbound shipment created")
print(f"   Route ID: {route_response['id']}")
print(f"   Origin: {transport_section['origin']}")
print(f"   Destination: {transport_section['destination']}")
print(f"   Transport type: {transport_section['transport_type']}")
print(f"   Weight: {transport_route['quantity_transported']:,} kg")
print(f"   CO₂e: {route_response.get('co2e', 'Calculating...')} kg")

Multi-Modal Shipments

For shipments using multiple transport modes (e.g., road + sea), create multiple transport sections for a single route:
# Multi-modal: Road + sea freight to overseas customer
# Create one transport route with multiple sections

# Step 1: Create the transport route
transport_route = {
    "start_date": "2024-01-15",
    "end_date": "2024-01-25",
    "quantity_transported": 5000,
    "unit_id": kg_unit['id'],
    "transport_direction": "downstream",
    "customer": "Customer B - New York",
}

route_response = requests.post(
    "https://api.dcycle.io/api/v1/transport_routes",
    headers=headers,
    json=transport_route
).json()

route_id = route_response['id']

# Step 2: Create transport sections for each leg
sections = [
    {
        "transport_route_id": route_id,
        "origin": "Munich, Germany",
        "destination": "Rotterdam, Netherlands",
        "transport_type": "road",
        "travel_method": "truck",
        "part": 1,  # First leg
    },
    {
        "transport_route_id": route_id,
        "origin": "Rotterdam, Netherlands",
        "destination": "New York, USA",
        "transport_type": "maritime",
        "part": 2,  # Second leg
    }
]

for section in sections:
    section_response = requests.post(
        "https://api.dcycle.io/api/v1/transport_sections",
        headers=headers,
        json=section
    ).json()
    print(f"   Part {section['part']}: {section['origin']}{section['destination']}")
    print(f"      Transport: {section['transport_type']}")
    print(f"      Distance: {section_response.get('kms', 'Calculating...')} km")

# Get total CO₂e for the route
route = requests.get(
    f"https://api.dcycle.io/api/v1/transport_routes/{route_id}",
    headers=headers
).json()

print(f"\n📊 Total shipment:")
print(f"   Total CO₂e: {route['co2e']:.2f} kg")

Step 2: Bulk Upload Outbound Shipments

For high-volume operations, upload shipments via CSV:

CSV Format

origin,destination,transport_type,travel_method,kms,quantity,unit,start_date,end_date,direction,customer,refrigerated
"Barcelona, Spain","Paris, France",road,truck,1050,2000,kg,2024-01-15,2024-01-16,downstream,Customer A,false
"Madrid, Spain","Lisbon, Portugal",road,truck,,1500,kg,2024-01-20,2024-01-21,downstream,Customer B,false
"Valencia, Spain","Milan, Italy",road,truck,1350,3000,kg,2024-02-01,2024-02-02,downstream,Customer C,true
"Barcelona, Spain","London, UK",unknown,,,2500,kg,2024-02-10,2024-02-12,downstream,Customer D,false
"Bilbao, Spain","Hamburg, Germany",maritime,,1800,8000,kg,2024-03-01,2024-03-08,downstream,Customer E,false
CSV Notes:
  • kms column: Leave empty to auto-calculate distance from origin/destination
  • transport_type: Use unknown if vehicle type is not known (origin/destination required)
  • travel_method: Only needed for road transport type (truck, car, etc.)
  • direction: Use downstream for Category 9 shipments

Upload and Process

import requests
import os
import time

headers = {
    "Authorization": f"Bearer {os.getenv('DCYCLE_API_KEY')}",
    "Content-Type": "application/json",
    "x-organization-id": os.getenv("DCYCLE_ORG_ID"),
    "x-user-id": os.getenv("DCYCLE_USER_ID"),
}

# Step 1: Get presigned upload URL
upload_response = requests.post(
    "https://api.dcycle.io/api/v1/logistics/bulk/csv",
    headers=headers
).json()

presigned_url = upload_response['upload_url']
status_url = upload_response['status_url']

# Step 2: Upload CSV to S3
with open('outbound_shipments_q1_2024.csv', 'rb') as f:
    requests.put(presigned_url, data=f)

print("✅ CSV uploaded, processing...")

# Step 3: Poll for completion
while True:
    status = requests.get(status_url, headers=headers).json()
    
    if status['status'] == 'completed':
        print(f"\n✅ Processed {status['records_processed']} outbound shipments")
        print(f"   Total CO₂e: {status['total_co2e']:,.2f} kg")
        print(f"   Total distance: {status['total_distance_km']:,.0f} km")
        print(f"   Category: Scope 3 - Category 9 (Downstream Transport)")
        break
    elif status['status'] == 'failed':
        print(f"❌ Upload failed: {status['error']}")
        break
    elif status['status'] == 'processing':
        progress = status.get('progress_percentage', 0)
        print(f"⏳ Processing... {progress}%")
    
    time.sleep(5)

Step 3: Query Category 9 Emissions

Get Category 9 Totals

import requests
import os

headers = {
    "Authorization": f"Bearer {os.getenv('DCYCLE_API_KEY')}",
    "Content-Type": "application/json",
    "x-organization-id": os.getenv("DCYCLE_ORG_ID"),
    "x-user-id": os.getenv("DCYCLE_USER_ID"),
}

# Query logistics emissions (Category 9)
response = requests.get(
    "https://api.dcycle.io/api/v1/logistics/report",
    headers=headers,
    params={
        "start_date": "2024-01-01",
        "end_date": "2024-12-31",
        "direction": "outbound",  # Category 9 only
    }
).json()

print(f"📊 Scope 3 Category 9: Downstream Transportation (2024)")
print("=" * 60)
print(f"   Total shipments: {response['total_shipments']:,}")
print(f"   Total distance: {response['total_distance_km']:,.0f} km")
print(f"   Total weight: {response['total_weight_kg']:,.0f} kg")
print(f"   Total CO₂e: {response['total_co2e']:,.0f} kg ({response['total_co2e']/1000:.1f} tonnes)")
print()

# Breakdown by transport type
print("   By Transport Type:")
for mode in response.get('by_transport_type', []):
    print(f"     - {mode['transport_type']}: {mode['co2e']:,.0f} kg ({mode['percentage']:.1f}%)")

Analyze by Customer Region

# Get emissions by customer destination
response = requests.get(
    "https://api.dcycle.io/api/v1/logistics/report",
    headers=headers,
    params={
        "start_date": "2024-01-01",
        "end_date": "2024-12-31",
        "direction": "outbound",
        "group_by": "destination_country"
    }
).json()

print("\n📊 Category 9 by Customer Country:")
print("-" * 50)

for country in response.get('by_destination_country', []):
    print(f"   {country['country']}: {country['co2e']:,.0f} kg CO₂e")
    print(f"      Shipments: {country['shipments']}")
    print(f"      Avg distance: {country['avg_distance_km']:,.0f} km")
    print()

Compare Category 9 to Other Scope 3

# Get total Scope 3 for context
scope3_response = requests.get(
    "https://api.dcycle.io/api/v1/total_impacts",
    headers=headers,
    params={
        "start_date": "2024-01-01",
        "end_date": "2024-12-31",
        "scopes": "scope_3"
    }
).json()

scope3_total = sum(i["emissions_per_day"] for i in scope3_response.get("items", []))
cat9_total = response['total_co2e']

print(f"\n📊 Category 9 Context:")
print(f"   Category 9: {cat9_total:,.0f} kg CO₂e")
print(f"   Total Scope 3: {scope3_total:,.0f} kg CO₂e")
if scope3_total > 0:
    print(f"   Category 9 as % of Scope 3: {cat9_total/scope3_total*100:.1f}%")

Best Practices

1. Ensure Complete Shipment Data

def validate_shipment_data(shipment):
    """Validate required shipment data"""
    
    required_fields = ['origin', 'destination', 'transport_type', 'quantity_transported']
    missing = [f for f in required_fields if not shipment.get(f)]
    
    if missing:
        return False, f"Missing required fields: {missing}"
    
    return True, "Valid shipment data"

# Validate before submission
is_valid, message = validate_shipment_data(shipment)
if not is_valid:
    print(f"⚠️ {message}")

2. Track by Sales Channel

Link logistics to your sales orders for traceability:
# Create transport route linked to customer
transport_route = {
    "start_date": "2024-03-01",
    "end_date": "2024-03-03",
    "quantity_transported": 1500,
    "unit_id": kg_unit['id'],
    "transport_direction": "downstream",
    "customer": "Customer C - Germany",  # Customer reference
    "name": "SO-2024-00789",  # Sales order reference
}

# Create transport section with location details
transport_section = {
    "transport_route_id": route_id,
    "origin": "Your warehouse, Spain",
    "destination": "Customer facility, Germany",
    "transport_type": "road",
    "travel_method": "truck",
}

3. Set Reduction Targets

# Track Category 9 intensity over time
def calculate_transport_intensity(year):
    """Calculate kg CO₂e per kg of goods shipped"""
    
    logistics = requests.get(
        "https://api.dcycle.io/api/v1/logistics/report",
        headers=headers,
        params={
            "start_date": f"{year}-01-01",
            "end_date": f"{year}-12-31",
            "direction": "outbound"
        }
    ).json()
    
    if logistics['total_weight_kg'] > 0:
        intensity = logistics['total_co2e'] / logistics['total_weight_kg']
        return intensity
    return 0

# Compare years
for year in [2022, 2023, 2024]:
    intensity = calculate_transport_intensity(year)
    print(f"{year}: {intensity:.3f} kg CO₂e/kg cargo")
Reduction Strategies for Category 9
  1. Consolidate shipments: Fewer, fuller trucks = lower emissions per kg
  2. Local distribution centers: Reduce last-mile distances
  3. Modal shift: Sea/rail instead of air/road where possible
  4. Customer engagement: Offer low-carbon delivery options
  5. Route optimization: Efficient delivery routes
  6. Electric last-mile: Partner with carriers using EVs for urban delivery

Troubleshooting

Issue: Missing Origin/Destination Data

# Fallback: Use your facility + customer country
if not shipment.get('destination'):
    # Get customer country from customer record
    customer = requests.get(
        f"https://api.dcycle.io/api/v1/customers/{customer_id}",
        headers=headers
    ).json()
    
    shipment['destination'] = f"{customer['city']}, {customer['country']}"
    print(f"⚠️  Using customer address: {shipment['destination']}")

# Or use manual distance if geocoding fails
shipment['manual_distance_km'] = 500  # Estimated distance

Issue: Unknown Transport Mode

# Suggest transport type based on context
def suggest_transport_type(origin_country, destination_country):
    """Suggest appropriate transport type based on route"""
    
    # International routes
    if origin_country != destination_country:
        # Check if likely sea routes (intercontinental)
        sea_countries = ['CN', 'JP', 'KR', 'US', 'BR', 'AU', 'IN']
        if origin_country in sea_countries or destination_country in sea_countries:
            return 'maritime'
        else:
            return 'road'  # European road freight
    
    # Domestic routes
    else:
        return 'road'

transport_type = suggest_transport_type('ES', 'FR')
print(f"Suggested transport type: {transport_type}")

# For road transport, also suggest travel method based on weight
def suggest_travel_method(weight_kg):
    """Suggest travel method for road transport"""
    if weight_kg > 3500:
        return 'truck'
    else:
        return 'car'

Issue: Category 9 Seems Too High/Low

# Benchmark Category 9 against revenue or units sold
sales_data = get_sales_data(2024)  # Your sales data

# Category 9 intensity by revenue
intensity_per_revenue = cat9_total / sales_data['total_revenue']
print(f"Category 9 intensity: {intensity_per_revenue:.2f} kg CO₂e per €1,000 revenue")

# Compare to industry benchmarks
if intensity_per_revenue < 1.0:
    print("✅ Below average intensity - efficient distribution")
elif intensity_per_revenue > 5.0:
    print("⚠️ High intensity - check for:")
    print("   - Long-distance customers")
    print("   - High air freight usage")
    print("   - Duplicate entries")

Next Steps