Create Logistics Request (v2)
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': '<content-type>'
}
};
fetch('https://api.dcycle.io/v2/logistics/requests', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v2/logistics/requests"
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"Content-Type": "<content-type>"
}
response = requests.post(url, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/v2/logistics/requests \
--header 'Content-Type: <content-type>' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>'{
"co2e": {},
"distance_km": {},
"tkm": {}
}Create Logistics Request (v2)
Create a logistics shipment with asynchronous emissions calculation
POST
/
v2
/
logistics
/
requests
Create Logistics Request (v2)
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': '<content-type>'
}
};
fetch('https://api.dcycle.io/v2/logistics/requests', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v2/logistics/requests"
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"Content-Type": "<content-type>"
}
response = requests.post(url, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/v2/logistics/requests \
--header 'Content-Type: <content-type>' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>'{
"co2e": {},
"distance_km": {},
"tkm": {}
}← Logistics API
v2 of Create Logistics Request. It accepts the
exact same request body and returns the same response shape, but the expensive
distance and emissions calculation is performed asynchronously instead of inline. This
keeps the request fast and predictable for high-volume integrations.
Same contract as v1. Headers, body parameters and validation are identical to
POST /v1/logistics/requests. Only the timing of the distance/emissions calculation
changes. See the v1 reference for the full list
of body parameters.v1 vs v2
| Behaviour | v1 (/v1/logistics/requests) | v2 (/v2/logistics/requests) |
|---|---|---|
Distance calculation (when distance_km omitted) | Calculated inline, returned in the response | Deferred to an async worker, null in the immediate response |
Emissions (co2e) | Calculated inline, returned in the response | Deferred to an async worker, null in the immediate response |
tkm | Returned in the response | Returned only if distance_km was provided; otherwise null until the async calc runs |
| Response latency | Higher (waits for geocoding + distance APIs) | Low (returns as soon as the record is persisted) |
In v2,
co2e is always null in the immediate response, and distance_km / tkm
are null whenever the client did not supply distance_km. These fields are populated
asynchronously. Read them back later via
GET /v1/logistics/requests (filter by movement_id)
once the calculation has completed.Request
Headers
string
required
Your API key for authentication
string
required
UUID of the organization the request belongs to
string
required
Must be
application/jsonBody Parameters
The request is identical to v1. Minimal example:curl -X POST "https://api.dcycle.io/v2/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",
"origin_country": "ES",
"load": 1000,
"load_unit": "kg",
"toc": "truck_diesel",
"year": 2024
}'
import os
import requests
response = requests.post(
"https://api.dcycle.io/v2/logistics/requests",
headers={
"x-api-key": os.environ["DCYCLE_API_KEY"],
"x-organization-id": os.environ["DCYCLE_ORG_ID"],
},
json={
"origin": "Madrid, Spain",
"destination": "Barcelona, Spain",
"origin_country": "ES",
"load": 1000,
"load_unit": "kg",
"toc": "truck_diesel",
"year": 2024,
},
)
data = response.json()
print(data["id"], data["co2e"]) # co2e is None while the async calculation is pending
const axios = require('axios');
axios.post('https://api.dcycle.io/v2/logistics/requests', {
origin: 'Madrid, Spain',
destination: 'Barcelona, Spain',
origin_country: 'ES',
load: 1000,
load_unit: 'kg',
toc: 'truck_diesel',
year: 2024,
}, {
headers: {
'x-api-key': process.env.DCYCLE_API_KEY,
'x-organization-id': process.env.DCYCLE_ORG_ID,
},
}).then(response => {
const { id, co2e } = response.data;
console.log(`Created: ${id}, co2e: ${co2e ?? 'pending'}`);
});
Response
Successful Response
The response shape matches v1, withco2e (and distance_km / tkm when not provided)
returned as null while the asynchronous calculation is pending.
{
"id": "f1e2d3c4-b5a6-7890-1234-567890abcdef",
"origin": "Madrid, Spain",
"destination": "Barcelona, Spain",
"origin_country": "ES",
"distance_km": null,
"load": 1000,
"load_unit": "kg",
"toc": "truck_diesel",
"category": "road",
"year": 2024,
"co2e": null,
"tkm": null,
"created_at": "2026-06-23T09:00:00Z",
"updated_at": "2026-06-23T09:00:00Z"
}
number | null
Total CO2 equivalent emissions in kilograms.
null in v2 until the asynchronous
calculation completes.number | null
Distance in kilometers. Echoes the value you provided;
null when omitted (it is
calculated asynchronously).number | null
Tonne-kilometers. Computed up front when
distance_km is provided; otherwise null
until the asynchronous calculation completes.All other response fields (
id, origin, destination, load, toc, category,
traceability fields, etc.) are returned exactly as documented for
v1.Reading back the calculated values
Because the calculation is asynchronous, poll the list endpoint (filtering by themovement_id you submitted) until kgco2e / distance_km are populated:
curl -X GET "https://api.dcycle.io/v1/logistics/requests?search=MOV-2024-001234" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}"
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 Unprocessable Entity
Cause: Invalid or missing required fields in the request body{
"detail": [
{
"loc": ["body", "origin"],
"msg": "field required",
"type": "value_error.missing"
}
]
}
Migrating from v1? No code changes are required beyond the URL prefix and handling
co2e (and possibly distance_km / tkm) being null in the immediate response.Related Endpoints
Bulk Create Requests (v2)
Create multiple requests in one call
List Requests
Retrieve requests with filtering and pagination
List Packages
View aggregated package emissions
List Vehicle Types
List available TOC codes for the toc field
Was this page helpful?