Create Logistics Requests (Bulk)
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({records: [{}], options: {}})
};
fetch('https://api.dcycle.io/v1/logistics/requests/bulk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v1/logistics/requests/bulk"
payload = {
"records": [{}],
"options": {}
}
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/v1/logistics/requests/bulk \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--data '
{
"records": [
{}
],
"options": {}
}
'{
"total_received": 123,
"total_processed": 123,
"success": 123,
"failed": 123,
"results": [
{}
],
"errors": [
{}
]
}Create Logistics Requests (Bulk)
Process multiple logistics shipments in a single request with optimized performance
POST
/
v1
/
logistics
/
requests
/
bulk
Create Logistics Requests (Bulk)
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({records: [{}], options: {}})
};
fetch('https://api.dcycle.io/v1/logistics/requests/bulk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v1/logistics/requests/bulk"
payload = {
"records": [{}],
"options": {}
}
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/v1/logistics/requests/bulk \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--data '
{
"records": [
{}
],
"options": {}
}
'{
"total_received": 123,
"total_processed": 123,
"success": 123,
"failed": 123,
"results": [
{}
],
"errors": [
{}
]
}Create Logistics Requests (Bulk)
Process multiple logistics requests in a single API call. Optimized for high-volume scenarios like daily batch uploads from logistics providers.New API: This endpoint is part of the new API architecture with improved design and maintainability.
Key Features
High Volume
Process up to 5,000 records per request
Optimized Performance
Internal caching of TOCs, hubs, and distances for faster processing
Error Handling
Continue processing even if some records fail with
continue_on_errorSame Schema
Uses the same record format as the single request endpoint
Request
Headers
string
required
Your API key for authenticationExample:
sk_live_1234567890abcdefstring
required
Your organization UUIDExample:
a8315ef3-dd50-43f8-b7ce-d839e68d51faBody Parameters
array
required
Array of logistics request objects. Each record uses the same schema as the single Create Logistics Request endpoint.Maximum items: 5,000
Show Record Fields
Show Record Fields
string
Origin location (address or hub name). Required if
distance_km not provided.string
Destination location (address or hub name). Required if
distance_km not provided.number
Distance in kilometers. If provided, takes priority over origin/destination.
number
Load of the shipment. If not provided, uses TOC default.
string
Unit of the load:
kg, ton, pallets, teu, feu. Default: kgnumber
Factor to multiply the load by (0-1). Default:
1.0string
Type of vehicle (e.g.,
van_diesel). If omitted, estimated from category.string
required
Vehicle category:
road, rail, maritime, air. Required if toc not provided.string
ISO 3166-1 alpha-2 country code for regional emission factors. Default:
GLOinteger
Year for emission factors. Default: current year.
boolean
Whether cleaning was done (increases emissions). Default:
falsestring
Unique shipment identifier for tracking.
string
Client or customer identifier.
date
Date of shipment (ISO 8601). Default: current date.
string
Stretch of the movement (e.g.,
first_mile, last_mile).string
Stage in the logistics chain (e.g.,
pickup, delivery).string
Vehicle license plate.
string
Trailer license plate.
boolean
Whether handled by a subcontractor. Default:
truenumber
Tonne-kilometers (if already calculated).
string
Unique package identifier for multi-leg tracking. Requires
movement_id.object
Processing options for the bulk operation.
Show Options Fields
Show Options Fields
boolean
If
true (default), continues processing remaining records when one fails.
If false, stops at the first error.Default: trueResponse
integer
Total number of records received in the request
integer
Total records processed (success + failed)
integer
Number of records processed successfully
integer
Number of records that failed
array
Array of successfully processed records with essential fields
Show Result Item Fields
Show Result Item Fields
array
Array of errors for failed records
Show Error Item Fields
Show Error Item Fields
Example
curl -X POST "https://api.dcycle.io/v1/logistics/requests/bulk" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"origin": "Madrid, Spain",
"destination": "Barcelona, Spain",
"load": 500,
"load_unit": "kg",
"category": "road",
"movement_id": "SHIP-001",
"client": "AMAZON"
},
{
"origin": "Madrid, Spain",
"destination": "Barcelona, Spain",
"load": 300,
"load_unit": "kg",
"category": "road",
"movement_id": "SHIP-002",
"client": "AMAZON"
},
{
"origin": "Valencia, Spain",
"destination": "Sevilla, Spain",
"load": 1000,
"load_unit": "kg",
"category": "road",
"movement_id": "SHIP-003",
"client": "ZARA"
}
],
"options": {
"continue_on_error": true
}
}'
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 = {
"records": [
{
"origin": "Madrid, Spain",
"destination": "Barcelona, Spain",
"load": 500,
"load_unit": "kg",
"category": "road",
"movement_id": "SHIP-001",
"client": "AMAZON"
},
{
"origin": "Madrid, Spain",
"destination": "Barcelona, Spain",
"load": 300,
"load_unit": "kg",
"category": "road",
"movement_id": "SHIP-002",
"client": "AMAZON"
},
{
"origin": "Valencia, Spain",
"destination": "Sevilla, Spain",
"load": 1000,
"load_unit": "kg",
"category": "road",
"movement_id": "SHIP-003",
"client": "ZARA"
}
],
"options": {
"continue_on_error": True
}
}
response = requests.post(
"https://api.dcycle.io/v1/logistics/requests/bulk",
headers=headers,
json=payload
)
result = response.json()
print(f"Processed: {result['success']}/{result['total_received']}")
print(f"Failed: {result['failed']}")
print(f"Total CO2e: {sum(r['co2e'] for r in result['results']):.2f} kg")
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 = {
records: [
{
origin: "Madrid, Spain",
destination: "Barcelona, Spain",
load: 500,
load_unit: "kg",
category: "road",
movement_id: "SHIP-001",
client: "AMAZON"
},
{
origin: "Madrid, Spain",
destination: "Barcelona, Spain",
load: 300,
load_unit: "kg",
category: "road",
movement_id: "SHIP-002",
client: "AMAZON"
},
{
origin: "Valencia, Spain",
destination: "Sevilla, Spain",
load: 1000,
load_unit: "kg",
category: "road",
movement_id: "SHIP-003",
client: "ZARA"
}
],
options: {
continue_on_error: true
}
};
axios.post(
'https://api.dcycle.io/v1/logistics/requests/bulk',
payload,
{ headers }
)
.then(response => {
const result = response.data;
console.log(`Processed: ${result.success}/${result.total_received}`);
console.log(`Failed: ${result.failed}`);
const totalCo2e = result.results.reduce((sum, r) => sum + r.co2e, 0);
console.log(`Total CO2e: ${totalCo2e.toFixed(2)} kg`);
})
.catch(error => console.error(error));
Successful Response
{
"total_received": 3,
"total_processed": 3,
"success": 3,
"failed": 0,
"results": [
{
"index": 0,
"id": "0d9b8817-fc47-47c3-b134-b3565ae1a57f",
"movement_id": "SHIP-001",
"package_id": null,
"co2e": 20.99
},
{
"index": 1,
"id": "683a0184-6dac-44ab-80a2-ce31b14ce927",
"movement_id": "SHIP-002",
"package_id": null,
"co2e": 12.59
},
{
"index": 2,
"id": "1048a12d-46e6-4e0d-955e-833d4693bcab",
"movement_id": "SHIP-003",
"package_id": null,
"co2e": 43.99
}
],
"errors": []
}
Response with Partial Errors
{
"total_received": 3,
"total_processed": 3,
"success": 2,
"failed": 1,
"results": [
{
"index": 0,
"id": "0d9b8817-fc47-47c3-b134-b3565ae1a57f",
"movement_id": "SHIP-001",
"package_id": null,
"co2e": 20.99
},
{
"index": 2,
"id": "1048a12d-46e6-4e0d-955e-833d4693bcab",
"movement_id": "SHIP-003",
"package_id": null,
"co2e": 43.99
}
],
"errors": [
{
"index": 1,
"movement_id": "SHIP-002",
"error": "TOC not found for toc=invalid_toc, category=None, region=EU"
}
]
}
Performance Optimizations
The bulk endpoint includes several optimizations for high-volume processing:TOC Caching
TOC Caching
All active vehicle types (TOCs) are pre-loaded at the start of the request, avoiding repeated database queries for each record.
Hub Caching
Hub Caching
Organization logistics hubs are pre-loaded, allowing instant name-to-address resolution without individual lookups.
Distance Caching
Distance Caching
Calculated distances are cached by route (origin, destination, category). Repeated routes reuse cached distances, reducing Google Maps API calls.Example: If 100 records share the same Madrid → Barcelona route, the distance is calculated only once.
Batch Database Operations
Batch Database Operations
Records are inserted in batches of 500 for efficient database writes.
Use Cases
Daily Batch Upload (Logistics Provider)
Process daily shipment data from a logistics provider:import pandas as pd
def upload_daily_shipments(csv_file: str):
"""Upload daily shipments from CSV file"""
df = pd.read_csv(csv_file)
records = []
for _, row in df.iterrows():
records.append({
"origin": row["origin"],
"destination": row["destination"],
"load": row["weight_kg"],
"load_unit": "kg",
"category": "road",
"movement_id": row["tracking_number"],
"client": row["client_code"],
"shipment_date": row["date"],
"distance_km": row.get("distance_km"), # Use if available
})
# Process in chunks of 5000
chunk_size = 5000
total_success = 0
total_failed = 0
for i in range(0, len(records), chunk_size):
chunk = records[i:i + chunk_size]
response = requests.post(
"https://api.dcycle.io/v1/logistics/requests/bulk",
headers=headers,
json={"records": chunk, "options": {"continue_on_error": True}}
)
result = response.json()
total_success += result["success"]
total_failed += result["failed"]
if result["errors"]:
print(f"Chunk {i//chunk_size + 1} errors: {result['errors']}")
print(f"Total: {total_success} success, {total_failed} failed")
return total_success, total_failed
# Example: Upload 400k daily records
upload_daily_shipments("daily_shipments_2024-01-15.csv")
Multi-leg Package Tracking (Bulk)
Track packages through multiple legs in a single request:def track_packages_bulk(packages_data: list):
"""
Track multiple packages with their legs in bulk.
packages_data format:
[
{
"package_key": "PKG-001",
"movement_id": "SHIP-001",
"legs": [
{"origin": "Madrid Hub", "destination": "Valencia Hub", "load_kg": 15},
{"origin": "Valencia Hub", "destination": "Barcelona Hub", "load_kg": 15},
]
},
...
]
"""
records = []
for pkg in packages_data:
for leg in pkg["legs"]:
records.append({
"origin": leg["origin"],
"destination": leg["destination"],
"load": leg["load_kg"],
"load_unit": "kg",
"category": "road",
"package_key": pkg["package_key"],
"movement_id": pkg["movement_id"],
})
response = requests.post(
"https://api.dcycle.io/v1/logistics/requests/bulk",
headers=headers,
json={"records": records, "options": {"continue_on_error": True}}
)
return response.json()
With Pre-calculated Distances
When you have pre-calculated distances (e.g., from your routing system), skip geocoding:records = [
{
"distance_km": 620, # Pre-calculated
"load": 500,
"load_unit": "kg",
"category": "road",
"origin_country": "ES",
"movement_id": "SHIP-001",
},
{
"distance_km": 450,
"load": 300,
"load_unit": "kg",
"category": "road",
"origin_country": "ES",
"movement_id": "SHIP-002",
},
]
response = requests.post(
"https://api.dcycle.io/v1/logistics/requests/bulk",
headers=headers,
json={"records": records}
)
Common Errors
401 Unauthorized
Cause: Missing or invalid API key{"detail": "Invalid API key for organization", "code": "INVALID_API_KEY"}
403 Forbidden
Cause: The authenticated user is not a member of the organization{"detail": "Logged User is not Member of Organization", "code": "LOGGED_USER_NOT_MEMBER"}
422 Validation Error
Cause: Invalid record format or missing required fields{
"detail": [
{
"loc": ["body", "records", 0, "category"],
"msg": "Please provide a category if toc is not present",
"type": "value_error"
}
]
}
toc or category, and either distance_km or both origin and destination.
Partial Failures
When some records fail butcontinue_on_error is true, the response includes both successful results and errors:
{
"success": 98,
"failed": 2,
"results": [...],
"errors": [
{"index": 5, "movement_id": "SHIP-006", "error": "TOC not found"},
{"index": 42, "movement_id": "SHIP-043", "error": "Load not found and no default available"}
]
}
errors array to identify and fix problematic records, then resubmit only the failed ones.
Limits
| Limit | Value |
|---|---|
| Maximum records per request | 5,000 |
| Maximum concurrent requests | 6 per API key |
| Request timeout | 5 minutes |
| Recommended batch size | 1,000 - 2,000 |
| Recommended concurrency | 5 (one below the limit) |
429 with a Retry-After header.
For very large uploads (e.g. 1.5M records), split into batches of 2,000 records and send up to 5 requests in parallel. Wait for one to finish before sending the next. On a
429 response, wait the number of seconds indicated in the Retry-After header before retrying.Related Endpoints
Create Single Request
Create a single logistics request
Get Requests
Retrieve all logistics requests with pagination
Get Packages
Retrieve packages with aggregated emissions
Get TOCs
Get available vehicle types
Was this page helpful?