> ## Documentation Index
> Fetch the complete documentation index at: https://code.dcycle.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Logistics Request

> Calculate CO2e emissions for a logistics shipment

# Create Logistics Request

Calculate CO2 equivalent (CO2e) emissions for a freight shipment with flexible parameters for origin/destination or direct distance input.

<Note>
  **New API**: This endpoint is part of the new API architecture with improved design and maintainability.
</Note>

## Request

### Headers

<ParamField header="x-api-key" type="string" required>
  Your API key for authentication

  **Example:** `sk_live_1234567890abcdef`
</ParamField>

<ParamField header="x-organization-id" type="string" required>
  Your organization UUID

  **Example:** `a8315ef3-dd50-43f8-b7ce-d839e68d51fa`
</ParamField>

### Body Parameters

<ParamField body="origin" type="string">
  Origin location of the shipment. Can be either:

  * **Address string**: City and country (e.g., `"Madrid, Spain"`)
  * **Hub Name**: Name of a logistics hub registered in your organization

  When a hub name is provided, the system automatically resolves it to the hub's registered address. Required if `distance_km` is not provided.

  **Examples:**

  * Address: `"Madrid, Spain"`
  * Hub Name: `"Madrid Distribution Center"`
</ParamField>

<ParamField body="destination" type="string">
  Destination location of the shipment. Can be either:

  * **Address string**: City and country (e.g., `"Barcelona, Spain"`)
  * **Hub Name**: Name of a logistics hub registered in your organization

  When a hub name is provided, the system automatically resolves it to the hub's registered address. Required if `distance_km` is not provided.

  **Examples:**

  * Address: `"Barcelona, Spain"`
  * Hub Name: `"Barcelona Warehouse"`
</ParamField>

<Note>
  **Hub Name Resolution**: When you provide a hub name as `origin` or `destination`, the system will:

  1. Look up the hub by name in your organization's registered hubs
  2. Validate that the hub is active and belongs to your organization
  3. Use the hub's registered address for distance calculation

  This is useful when you have predefined warehouse or distribution center locations. If the provided value does not match any hub name in your organization, it will be treated as a literal address string.
</Note>

<ParamField body="distance_km" type="number">
  Distance in kilometers between origin and destination. If provided, takes priority over `origin` and `destination`.

  **Example:** `500`
</ParamField>

<ParamField body="load" type="number">
  Load of the shipment. If not provided, it will be calculated from the TOC or category.

  **Example:** `1000`
</ParamField>

<ParamField body="load_unit" type="string">
  Unit of the load.

  **Available values:** `kg`, `ton`, `pallets`, `teu`, `feu`

  **Default:** `kg`
</ParamField>

<ParamField body="load_factor" type="number">
  Factor to divide the load by (between 0 and 1). Example: 100 pallets with 0.5 factor is 50 pallets.

  **Default:** `1.0`
</ParamField>

<ParamField body="toc" type="string">
  Type of vehicle to use for calculation. If omitted, it will be estimated from the `category` provided.

  **Example:** `"van_diesel"`
</ParamField>

<ParamField body="category" type="string">
  Category of the vehicle. Required if `toc` is not provided.

  **Available values:** `road`, `rail`, `maritime`, `air`

  **Example:** `"road"`
</ParamField>

<ParamField body="origin_country" type="string">
  Country ISO 3166-1 alpha-2 code of the origin to use the region's emission factors. If not provided, global factors will be used.

  **Default:** `GLO`

  **Example:** `ES`
</ParamField>

<ParamField body="year" type="integer">
  Year of the emission factor to use. If not provided, current year will be used.

  **Example:** `2024`
</ParamField>

<ParamField body="cleaning" type="boolean">
  If cleaning has been done, it will increase the emissions.

  **Default:** `false`
</ParamField>

### Traceability Parameters

These optional parameters allow you to track shipments with full traceability for logistics providers.

<ParamField body="movement_id" type="string">
  Unique identifier for the shipment movement, used for tracking and deduplication.

  **Example:** `"MOV-2024-001234"`
</ParamField>

<ParamField body="client" type="string">
  Client or customer identifier for the shipment.

  **Example:** `"CORREOS-EXPRESS"`
</ParamField>

<ParamField body="shipment_date" type="date">
  Date of the shipment (ISO 8601 format). If not provided, current date will be used.

  **Example:** `"2024-11-25"`
</ParamField>

<ParamField body="movement_stretch" type="string">
  Stretch or segment of the movement (e.g., first mile, last mile).

  **Example:** `"last_mile"`
</ParamField>

<ParamField body="movement_stage" type="string">
  Stage of the movement in the logistics chain.

  **Example:** `"delivery"`
</ParamField>

<ParamField body="vehicle_license_plate" type="string">
  License plate of the vehicle used for the shipment.

  **Example:** `"1234-ABC"`
</ParamField>

<ParamField body="trailer_license_plate" type="string">
  License plate of the trailer, if applicable.

  **Example:** `"5678-XYZ"`
</ParamField>

<ParamField body="subcontractor" type="boolean">
  Whether the shipment is handled by a subcontractor.

  **Default:** `true`
</ParamField>

<ParamField body="tkm" type="number">
  Tonne-kilometers (load in tonnes multiplied by distance in km). If provided, used directly for calculations instead of computing from load and distance.

  **Example:** `500.0`
</ParamField>

<ParamField body="hub_id" type="string">
  Identifier of the logistics hub associated with this shipment. This parameter serves two main purposes:

  1. **Emissions allocation**: Identifies that a specific load for a client was stored in a hub, allowing the system to assign the corresponding hub storage emissions.
  2. **Origin substitution**: When the hub address is registered in the system, it will be automatically used as the origin point for the leg, replacing the specified origin.

  **Example:** `"HUB-MAD-001"`
</ParamField>

<Note>
  **Hub Integration**: When you provide a `hub_id`, the system automatically handles two things: it attributes the appropriate storage emissions from that hub to your shipment, and if the hub has a registered address, it overrides the leg's origin with the hub's location. This ensures accurate emission tracking for warehouse and cross-docking operations.
</Note>

### Package Parameters (Multi-leg Shipments)

These parameters enable tracking of packages that travel through multiple legs.

<ParamField body="package_key" type="string">
  Unique identifier for the package. When provided, this leg will be associated with the package. Requires `movement_id` to group packages into shipments.

  **Example:** `"26830007899150601093463"`
</ParamField>

<Note>
  **Package Tracking**: When you provide `package_key`, the system automatically creates or finds the package and associates this leg with it. Multiple legs with the same `package_key` will be grouped together, and the package's total distance and emissions will be aggregated.
</Note>

## Response

<ResponseField name="id" type="string">
  Unique identifier for the logistics request
</ResponseField>

<ResponseField name="co2e" type="number">
  Total CO2 equivalent emissions in kilograms
</ResponseField>

<ResponseField name="created_at" type="datetime">
  Timestamp when the request was created
</ResponseField>

<ResponseField name="updated_at" type="datetime | null">
  Timestamp when the request was last updated
</ResponseField>

<ResponseField name="origin" type="string">
  Shipment origin address. If a hub name was provided in the request, this will contain the resolved hub address.
</ResponseField>

<ResponseField name="destination" type="string">
  Shipment destination address. If a hub name was provided in the request, this will contain the resolved hub address.
</ResponseField>

<ResponseField name="distance_km" type="number">
  Distance in kilometers (if provided or calculated)
</ResponseField>

<ResponseField name="load" type="number">
  Transported load
</ResponseField>

<ResponseField name="load_unit" type="string">
  Load unit of measurement
</ResponseField>

<ResponseField name="category" type="string">
  Vehicle category used
</ResponseField>

<ResponseField name="toc" type="string">
  Type of vehicle (if provided)
</ResponseField>

<ResponseField name="origin_country" type="string">
  Origin country code
</ResponseField>

<ResponseField name="year" type="integer">
  Year used for emission factors
</ResponseField>

<ResponseField name="movement_id" type="string">
  Unique identifier for the shipment movement
</ResponseField>

<ResponseField name="client" type="string">
  Client or customer identifier
</ResponseField>

<ResponseField name="shipment_date" type="date">
  Date of the shipment
</ResponseField>

<ResponseField name="movement_stretch" type="string">
  Stretch or segment of the movement
</ResponseField>

<ResponseField name="movement_stage" type="string">
  Stage of the movement in the logistics chain
</ResponseField>

<ResponseField name="vehicle_license_plate" type="string">
  License plate of the vehicle
</ResponseField>

<ResponseField name="trailer_license_plate" type="string">
  License plate of the trailer
</ResponseField>

<ResponseField name="subcontractor" type="boolean">
  Whether handled by a subcontractor
</ResponseField>

<ResponseField name="tkm" type="number">
  Tonne-kilometers calculated or provided
</ResponseField>

<ResponseField name="hub_id" type="string">
  Logistics hub identifier
</ResponseField>

<ResponseField name="package_id" type="string">
  UUID of the associated package (if `package_key` was provided)
</ResponseField>

<ResponseField name="package_key" type="string">
  Package identifier (if provided in request)
</ResponseField>

## Example

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST "https://api.dcycle.io/v1/logistics/requests" \
    -H "x-api-key: ${DCYCLE_API_KEY}" \
    -H "x-organization-id: ${DCYCLE_ORG_ID}" \
    -H "Content-Type: application/json" \
    -d '{
      "origin": "Madrid, Spain",
      "destination": "Barcelona, Spain",
      "load": 1000,
      "load_unit": "kg",
      "category": "road"
    }'
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests
  import os

  api_key = os.getenv("DCYCLE_API_KEY")
  org_id = os.getenv("DCYCLE_ORG_ID")

  headers = {
      "x-api-key": api_key,
      "x-organization-id": org_id,
      "Content-Type": "application/json"
  }

  payload = {
      "origin": "Madrid, Spain",
      "destination": "Barcelona, Spain",
      "load": 1000,
      "load_unit": "kg",
      "category": "road"
  }

  response = requests.post(
      "https://api.dcycle.io/v1/logistics/requests",
      headers=headers,
      json=payload
  )

  result = response.json()
  print(f"Request ID: {result['id']}")
  print(f"CO2e: {result['co2e']} kg")
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const axios = require('axios');

  const apiKey = process.env.DCYCLE_API_KEY;
  const orgId = process.env.DCYCLE_ORG_ID;

  const headers = {
    'x-api-key': apiKey,
    'x-organization-id': orgId,
    'Content-Type': 'application/json'
  };

  const payload = {
    origin: "Madrid, Spain",
    destination: "Barcelona, Spain",
    load: 1000,
    load_unit: "kg",
    category: "road"
  };

  axios.post(
    'https://api.dcycle.io/v1/logistics/requests',
    payload,
    { headers }
  )
  .then(response => {
    console.log(`Request ID: ${response.data.id}`);
    console.log(`CO2e: ${response.data.co2e} kg`);
  })
  .catch(error => console.error(error));
  ```
</CodeGroup>

### Successful Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "0b08bffd-a1e3-48cb-a477-aefa59131934",
  "origin": "CALLE MAESTRO FALLA 11, SALAMANCA, 37003",
  "destination": "C/ MONTERA, 25-27 - P.I. LOS VILLARES, VILLARES DE LA REINA, 37184",
  "origin_country": "ES",
  "distance_km": 3.4447,
  "load": 1.0,
  "load_unit": "kg",
  "load_factor": 1.0,
  "toc": "generic_average_road",
  "category": "road",
  "year": 2025,
  "cleaning": false,
  "co2e": 0.000528,
  "tkm": 0.00344,
  "movement_id": "9883000788469370",
  "client": "AMAZON",
  "shipment_date": "2025-05-19",
  "movement_stretch": "RECOGIDA",
  "movement_stage": "FIRST_MILE",
  "package_key": "98830007884693701030068",
  "package_id": "128be1de-9aa0-4c7d-891f-5daf5467107e",
  "subcontractor": false,
  "vehicle_license_plate": null,
  "trailer_license_plate": null,
  "hub_id": null,
  "created_at": "2025-12-04T06:42:35.973485",
  "updated_at": "2025-12-04T06:42:35.973489"
}
```

## Common Errors

### 401 Unauthorized

**Cause:** Missing or invalid API key

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": "Invalid API key",
  "code": "INVALID_API_KEY"
}
```

**Solution:** Verify your API key is valid and active. Get a new one from [Settings → API](https://app.dcycle.io/settings/api).

### 404 Not Found

**Cause:** Organization not found

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "code": "ORGANIZATION_NOT_FOUND",
  "detail": "Organization with id=UUID('...') not found"
}
```

**Solution:** Verify that the `x-organization-id` header contains a valid organization UUID.

### 422 Validation Error

**Cause:** Missing required parameters or invalid values

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": [
    {
      "loc": ["body", "category"],
      "msg": "Please provide a category if toc is not present",
      "type": "value_error"
    }
  ]
}
```

**Solution:** Ensure that either `toc` or `category` is provided. If using addresses, provide both `origin` and `destination`, or use `distance_km` instead.

### 404 Hub Not Found

**Cause:** A hub name was provided as origin/destination, but the hub is not active or doesn't belong to your organization

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "code": "NOT_FOUND",
  "detail": "Origin hub not found"
}
```

**Solution:** Verify that:

* The hub name is correct and exists in your organization
* The hub status is `active` (not `inactive`, `error`, or `archived`)

### 400 Hub Has No Address

**Cause:** A hub name was provided as origin/destination, but the hub doesn't have an address configured

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "code": "BAD_REQUEST",
  "detail": "Origin hub has no address configured"
}
```

**Solution:** Configure an address for the hub in your organization settings before using it as origin/destination.

## Use Cases

### Calculate Emissions with Addresses

Most common use case - let the API calculate distance from addresses:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def calculate_shipment_emissions(origin, destination, load_kg):
    """Calculate emissions for a shipment between two locations"""
    response = requests.post(
        "https://api.dcycle.io/v1/logistics/requests",
        headers=headers,
        json={
            "origin": origin,
            "destination": destination,
            "load": load_kg,
            "load_unit": "kg",
            "category": "road"
        }
    )

    result = response.json()
    return {
        "co2e": result["co2e"],
        "distance": result.get("distance_km")
    }

# Example usage
emissions = calculate_shipment_emissions(
    origin="Madrid, Spain",
    destination="Barcelona, Spain",
    load_kg=1500
)
print(f"Emissions: {emissions['co2e']} kg CO2e")
```

### Using Hub Names for Origin/Destination

If you have logistics hubs registered in your organization, you can use their names instead of addresses:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def calculate_hub_to_hub_emissions(origin_hub_name, destination_hub_name, load_kg):
    """Calculate emissions between two logistics hubs"""
    response = requests.post(
        "https://api.dcycle.io/v1/logistics/requests",
        headers=headers,
        json={
            "origin": origin_hub_name,        # Hub name
            "destination": destination_hub_name,  # Hub name
            "load": load_kg,
            "load_unit": "kg",
            "category": "road"
        }
    )

    result = response.json()
    return {
        "co2e": result["co2e"],
        "origin_resolved": result["origin"],      # Hub address
        "destination_resolved": result["destination"],  # Hub address
        "distance": result.get("distance_km")
    }

# Example: Shipment between Madrid and Barcelona hubs
emissions = calculate_hub_to_hub_emissions(
    origin_hub_name="Madrid Distribution Center",
    destination_hub_name="Barcelona Warehouse",
    load_kg=1500
)
print(f"From: {emissions['origin_resolved']}")
print(f"To: {emissions['destination_resolved']}")
print(f"Emissions: {emissions['co2e']} kg CO2e")
```

You can also mix hub names with addresses:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Hub to customer address
response = requests.post(
    "https://api.dcycle.io/v1/logistics/requests",
    headers=headers,
    json={
        "origin": "Madrid Distribution Center",  # Hub name
        "destination": "Customer Address, Barcelona, Spain",  # Regular address
        "load": 25,
        "load_unit": "kg",
        "category": "road"
    }
)
```

### Using Known Distance

If you already know the distance, skip geocoding:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def calculate_with_distance(distance_km, load_kg, country="GLO"):
    """Calculate emissions when distance is already known"""
    response = requests.post(
        "https://api.dcycle.io/v1/logistics/requests",
        headers=headers,
        json={
            "distance_km": distance_km,
            "load": load_kg,
            "load_unit": "kg",
            "category": "road",
            "origin_country": country  # For regional emission factors
        }
    )

    return response.json()

# Example: 500km shipment in Spain
result = calculate_with_distance(500, 1000, "ES")
print(f"CO2e: {result['co2e']} kg")
```

### Comparing Transport Modes

Compare emissions across different transport categories:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def compare_transport_modes(origin, destination, load):
    """Compare emissions for different transport modes"""
    modes = ["road", "rail", "air", "maritime"]
    results = {}

    for mode in modes:
        response = requests.post(
            "https://api.dcycle.io/v1/logistics/requests",
            headers=headers,
            json={
                "origin": origin,
                "destination": destination,
                "load": load,
                "load_unit": "kg",
                "category": mode
            }
        )

        if response.status_code == 200:
            data = response.json()
            results[mode] = data["co2e"]

    return results

# Compare modes for Barcelona to Madrid shipment
comparison = compare_transport_modes(
    "Barcelona, Spain",
    "Madrid, Spain",
    1000
)

for mode, emissions in comparison.items():
    print(f"{mode}: {emissions:.2f} kg CO2e")
```

### Logistics Provider Integration (Full Traceability)

For logistics providers like courier companies that need complete shipment tracking:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def create_tracked_shipment(shipment_data):
    """Create a shipment with full traceability for logistics providers"""
    response = requests.post(
        "https://api.dcycle.io/v1/logistics/requests",
        headers=headers,
        json={
            # Core emission parameters
            "origin": shipment_data["origin"],
            "destination": shipment_data["destination"],
            "load": shipment_data["weight_kg"],
            "load_unit": "kg",
            "category": "road",
            "origin_country": "ES",

            # Traceability parameters
            "movement_id": shipment_data["tracking_number"],
            "client": shipment_data["client_code"],
            "shipment_date": shipment_data["date"],
            "movement_stretch": shipment_data.get("stretch", "delivery"),
            "movement_stage": shipment_data.get("stage", "last_mile"),
            "vehicle_license_plate": shipment_data.get("vehicle_plate"),
            "trailer_license_plate": shipment_data.get("trailer_plate"),
            "subcontractor": shipment_data.get("is_subcontracted", False),
        }
    )

    return response.json()

# Example: Correos Express shipment
shipment = create_tracked_shipment({
    "tracking_number": "CE-2024-987654",
    "client_code": "CORREOS-EXPRESS",
    "origin": "Centro Logistico Madrid, Spain",
    "destination": "Barcelona, Spain",
    "weight_kg": 25,
    "date": "2024-11-25",
    "stretch": "hub_to_destination",
    "stage": "delivery",
    "vehicle_plate": "1234-ABC",
    "is_subcontracted": False
})

print(f"Tracking: {shipment['movement_id']}")
print(f"CO2e: {shipment['co2e']} kg")
```

### Bulk Shipment Processing

For high-volume scenarios (hundreds to thousands of shipments), use the dedicated bulk endpoint:

<Card title="Create Logistics Requests (Bulk)" icon="layer-group" href="/api-reference/logistics/create-requests-bulk">
  Process up to 5,000 records per request with optimized performance, caching, and partial error handling.
</Card>

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# For bulk processing, use the dedicated bulk endpoint
response = requests.post(
    "https://api.dcycle.io/v1/logistics/requests/bulk",
    headers=headers,
    json={
        "records": shipments,  # List of up to 5,000 records
        "options": {"continue_on_error": True}
    }
)

result = response.json()
print(f"Processed: {result['success']}/{result['total_received']}")
print(f"Total CO2e: {sum(r['co2e'] for r in result['results']):.2f} kg")
```

### Single Package Tracking

Track a single package with one leg (simplest case):

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Create a leg associated with a package
response = requests.post(
    "https://api.dcycle.io/v1/logistics/requests",
    headers=headers,
    json={
        "origin": "Madrid Hub",
        "destination": "Customer Address, Madrid",
        "load": 5,
        "load_unit": "kg",
        "category": "road",

        # Package tracking
        "movement_id": "SHIP-2024-001",      # Shipment identifier
        "package_key": "PKG-2024-000001",    # Unique package identifier

        # Optional
        "client": "AMAZON",
        "shipment_date": "2024-11-25",
    }
)

result = response.json()
print(f"Package {result['package_key']} - CO2e: {result['co2e']} kg")
```

### Multiple Packages in One Shipment

Track multiple packages belonging to the same shipment. Each package has its own `package_key` but shares the same `movement_id`:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def create_shipment_with_packages(movement_id: str, packages: list):
    """
    Create a shipment with multiple packages.
    Each package is a single-leg delivery in this example.
    """
    results = []

    for pkg in packages:
        response = requests.post(
            "https://api.dcycle.io/v1/logistics/requests",
            headers=headers,
            json={
                "origin": pkg["origin"],
                "destination": pkg["destination"],
                "load": pkg["weight_kg"],
                "load_unit": "kg",
                "category": "road",

                # Same movement_id groups all packages into one shipment
                "movement_id": movement_id,
                # Each package has unique key
                "package_key": pkg["package_key"],

                "client": pkg.get("client", "DEFAULT"),
            }
        )
        results.append(response.json())

    return results

# Example: Shipment with 3 packages going to different destinations
packages = [
    {"package_key": "PKG-001", "origin": "Madrid Hub", "destination": "Address A, Madrid", "weight_kg": 2, "client": "AMAZON"},
    {"package_key": "PKG-002", "origin": "Madrid Hub", "destination": "Address B, Madrid", "weight_kg": 5, "client": "AMAZON"},
    {"package_key": "PKG-003", "origin": "Madrid Hub", "destination": "Address C, Madrid", "weight_kg": 1, "client": "AMAZON"},
]

results = create_shipment_with_packages("SHIP-2024-100", packages)

total_co2e = sum(r['co2e'] for r in results)
print(f"Shipment SHIP-2024-100: {len(results)} packages, {total_co2e:.2f} kg CO2e total")

# Later, retrieve all packages for this shipment:
# GET /v1/logistics/packages?movement_id=SHIP-2024-100
```

### Multi-leg Package Tracking

Track a package through multiple legs of its journey. Each leg is created separately, and the system automatically aggregates emissions per package:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def track_package_journey(package_key: str, movement_id: str, legs: list):
    """
    Track a package through multiple legs.

    Args:
        package_key: Unique package identifier
        movement_id: Shipment identifier (groups packages)
        legs: List of leg data (origin, destination, load, etc.)
    """
    results = []

    for leg in legs:
        response = requests.post(
            "https://api.dcycle.io/v1/logistics/requests",
            headers=headers,
            json={
                # Core parameters
                "origin": leg["origin"],
                "destination": leg["destination"],
                "load": leg["load_kg"],
                "load_unit": "kg",
                "category": leg.get("category", "road"),

                # Package tracking
                "package_key": package_key,
                "movement_id": movement_id,

                # Optional traceability
                "client": leg.get("client"),
                "shipment_date": leg.get("date"),
            }
        )
        results.append(response.json())

    return results

# Example: Package traveling through 3 legs
legs = [
    {"origin": "Madrid Hub", "destination": "Valencia Hub", "load_kg": 15},
    {"origin": "Valencia Hub", "destination": "Barcelona Hub", "load_kg": 15},
    {"origin": "Barcelona Hub", "destination": "Final Address, Barcelona", "load_kg": 15},
]

results = track_package_journey(
    package_key="PKG-2024-123456",
    movement_id="SHIP-2024-001",
    legs=legs
)

# Get aggregated package data
package_response = requests.get(
    f"https://api.dcycle.io/v1/logistics/packages?movement_id=SHIP-2024-001",
    headers=headers
)
print(f"Total package emissions: {package_response.json()['items'][0]['total_co2e']} kg CO2e")
```

## Migration from Legacy API

If you're migrating from the legacy `/api/v1/logistics/shipment` endpoint:

<CardGroup cols={2}>
  <Card title="URL Change" icon="link">
    **Old:** `/api/v1/logistics/shipment`

    **New:** `/v1/logistics/requests`
  </Card>

  <Card title="Headers Update" icon="header">
    **Removed:** `x-user-id` (not needed)

    **Keep:** `Authorization`, `x-organization-id`
  </Card>

  <Card title="Response Changes" icon="code">
    **Added:** `id` field for tracking

    **Added:** `created_at`, `updated_at` timestamps
  </Card>

  <Card title="Field Names" icon="edit">
    Most field names remain the same

    Check validation rules for `category` vs `toc`
  </Card>
</CardGroup>

<Tip>
  Both APIs will be supported during the migration period. New integrations should use `/v1/logistics/requests`.
</Tip>

## Related Endpoints

<CardGroup cols={2}>
  <Card title="Create Requests (Bulk)" icon="layer-group" href="/api-reference/logistics/create-requests-bulk">
    Process up to 5,000 shipments in a single request
  </Card>

  <Card title="Get Logistics Requests" icon="list" href="/api-reference/logistics/get-requests">
    Retrieve all logistics requests (legs) with pagination
  </Card>

  <Card title="Get Packages" icon="box" href="/api-reference/logistics/get-packages">
    Retrieve all packages with aggregated emissions
  </Card>

  <Card title="Get Package by ID" icon="box-open" href="/api-reference/logistics/get-package">
    Get a package with all its legs
  </Card>

  <Card title="Get Available Vehicle Types" icon="truck" href="/api-reference/logistics/get-tocs">
    Retrieve all available TOCs
  </Card>

  <Card title="Authentication Guide" icon="key" href="/docs/authentication">
    Learn how to get your API key
  </Card>
</CardGroup>
