curl -X POST "https://api.dcycle.io/v2/vehicles" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "Idempotency-Key: 6f5e4d3c-2b1a-4f0e-9d8c-7b6a5f4e3d2c" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"license_plate": "1234 ABC",
"name": "Delivery van 01",
"type": "freight",
"ownership": "owned",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
"registration_year": 2021,
"client_row_id": "FLEET-001"
}
]
}'
import os
import uuid
import requests
response = requests.post(
"https://api.dcycle.io/v2/vehicles",
headers={
"x-api-key": os.environ["DCYCLE_API_KEY"],
"x-organization-id": os.environ["DCYCLE_ORG_ID"],
"Idempotency-Key": str(uuid.uuid4()), # keep it to retry this same batch
},
json={
"records": [
{
"license_plate": "1234 ABC",
"type": "passenger",
"ownership": "rented",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
}
]
},
timeout=60,
)
response.raise_for_status()
for item in response.json()["items"]:
print(item["client_row_id"], item["vehicle"]["id"])
{
"items": [
{
"source_row_index": 0,
"client_row_id": "FLEET-001",
"vehicle": {
"id": "8a7b6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
"organization_id": "a8315ef3-dd50-43f8-b7ce-d839e68d51fa",
"license_plate": "1234 ABC",
"name": "Delivery van 01",
"type": "freight",
"ownership": "owned",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
"registration_year": 2021,
"market_segment": null,
"size": null,
"status": "active",
"created_at": "2026-10-19T09:12:44.031Z",
"updated_at": "2026-10-19T09:12:44.031Z"
}
}
]
}
{
"type": "https://code.dcycle.io/api-reference/errors#BULK_RECORDS_REJECTED",
"title": "Unprocessable Entity",
"status": 422,
"code": "BULK_RECORDS_REJECTED",
"detail": "1 of the submitted records are invalid; nothing was written.",
"errors": [
{
"source_row_index": 0,
"client_row_id": "FLEET-001",
"error_code": "LICENSE_PLATE_ALREADY_EXISTS",
"error_params": { "field": "license_plate", "value": "1234 ABC" }
}
],
"rejected": 1,
"request_id": "b2248a31-0f1b-4a7d-83ce-b29bd5977b4c"
}
{ "dry_run": true, "submitted": 1, "valid": 1 }
Create Vehicles (v2)
Create up to 1,000 vehicles in one request and get them back
POST
/
v2
/
vehicles
curl -X POST "https://api.dcycle.io/v2/vehicles" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "Idempotency-Key: 6f5e4d3c-2b1a-4f0e-9d8c-7b6a5f4e3d2c" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"license_plate": "1234 ABC",
"name": "Delivery van 01",
"type": "freight",
"ownership": "owned",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
"registration_year": 2021,
"client_row_id": "FLEET-001"
}
]
}'
import os
import uuid
import requests
response = requests.post(
"https://api.dcycle.io/v2/vehicles",
headers={
"x-api-key": os.environ["DCYCLE_API_KEY"],
"x-organization-id": os.environ["DCYCLE_ORG_ID"],
"Idempotency-Key": str(uuid.uuid4()), # keep it to retry this same batch
},
json={
"records": [
{
"license_plate": "1234 ABC",
"type": "passenger",
"ownership": "rented",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
}
]
},
timeout=60,
)
response.raise_for_status()
for item in response.json()["items"]:
print(item["client_row_id"], item["vehicle"]["id"])
{
"items": [
{
"source_row_index": 0,
"client_row_id": "FLEET-001",
"vehicle": {
"id": "8a7b6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
"organization_id": "a8315ef3-dd50-43f8-b7ce-d839e68d51fa",
"license_plate": "1234 ABC",
"name": "Delivery van 01",
"type": "freight",
"ownership": "owned",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
"registration_year": 2021,
"market_segment": null,
"size": null,
"status": "active",
"created_at": "2026-10-19T09:12:44.031Z",
"updated_at": "2026-10-19T09:12:44.031Z"
}
}
]
}
{
"type": "https://code.dcycle.io/api-reference/errors#BULK_RECORDS_REJECTED",
"title": "Unprocessable Entity",
"status": 422,
"code": "BULK_RECORDS_REJECTED",
"detail": "1 of the submitted records are invalid; nothing was written.",
"errors": [
{
"source_row_index": 0,
"client_row_id": "FLEET-001",
"error_code": "LICENSE_PLATE_ALREADY_EXISTS",
"error_params": { "field": "license_plate", "value": "1234 ABC" }
}
],
"rejected": 1,
"request_id": "b2248a31-0f1b-4a7d-83ce-b29bd5977b4c"
}
{ "dry_run": true, "submitted": 1, "valid": 1 }
← Vehicles API
Create one or many vehicles of your fleet. A vehicle is master data: creating it calculates nothing (its emissions
come from its consumptions), so the request is synchronous: it answers
201 Created with every vehicle, in the order you sent them, ready to take consumptions.
Beta. Part of the bulk ingest API, currently in beta. The contract may still change before general availability.
curl -X POST "https://api.dcycle.io/v2/vehicles" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "Idempotency-Key: 6f5e4d3c-2b1a-4f0e-9d8c-7b6a5f4e3d2c" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"license_plate": "1234 ABC",
"name": "Delivery van 01",
"type": "freight",
"ownership": "owned",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
"registration_year": 2021,
"client_row_id": "FLEET-001"
}
]
}'
import os
import uuid
import requests
response = requests.post(
"https://api.dcycle.io/v2/vehicles",
headers={
"x-api-key": os.environ["DCYCLE_API_KEY"],
"x-organization-id": os.environ["DCYCLE_ORG_ID"],
"Idempotency-Key": str(uuid.uuid4()), # keep it to retry this same batch
},
json={
"records": [
{
"license_plate": "1234 ABC",
"type": "passenger",
"ownership": "rented",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
}
]
},
timeout=60,
)
response.raise_for_status()
for item in response.json()["items"]:
print(item["client_row_id"], item["vehicle"]["id"])
{
"items": [
{
"source_row_index": 0,
"client_row_id": "FLEET-001",
"vehicle": {
"id": "8a7b6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
"organization_id": "a8315ef3-dd50-43f8-b7ce-d839e68d51fa",
"license_plate": "1234 ABC",
"name": "Delivery van 01",
"type": "freight",
"ownership": "owned",
"country": "ES",
"unknown_vehicle_id": "0ec95def-e866-4d04-89a0-87d8b4ba4527",
"vehicle_fuel_ids": ["407ff7e3-aa7f-4844-94b1-e621b6fbdd5e"],
"registration_year": 2021,
"market_segment": null,
"size": null,
"status": "active",
"created_at": "2026-10-19T09:12:44.031Z",
"updated_at": "2026-10-19T09:12:44.031Z"
}
}
]
}
{
"type": "https://code.dcycle.io/api-reference/errors#BULK_RECORDS_REJECTED",
"title": "Unprocessable Entity",
"status": 422,
"code": "BULK_RECORDS_REJECTED",
"detail": "1 of the submitted records are invalid; nothing was written.",
"errors": [
{
"source_row_index": 0,
"client_row_id": "FLEET-001",
"error_code": "LICENSE_PLATE_ALREADY_EXISTS",
"error_params": { "field": "license_plate", "value": "1234 ABC" }
}
],
"rejected": 1,
"request_id": "b2248a31-0f1b-4a7d-83ce-b29bd5977b4c"
}
{ "dry_run": true, "submitted": 1, "valid": 1 }
How it works
- Every record is checked, with the rules of the Data Importer: the vehicle class and its fuels exist and the
fuels are ones that class can run on, the country is known and the plate is free. If any record is invalid the
whole request is rejected with
422and nothing is created; the answer lists every invalid record. - Every vehicle is created in one transaction and returned, in the order sent.
source_row_indexis the position of the record inrecords, andclient_row_idechoes yours. - The vehicles belong to the
x-organization-idorganization. A record cannot name another one: send each organization’s vehicles with its ownx-organization-id.
Request
Headers
string
required
Your API key (see Authentication).
string
required
The organization the vehicles belong to.
string
required
1 to 255 characters, unique per batch. A retry with the same key and body answers the same vehicles (with
Idempotent-Replayed: true) instead of creating them again; the same key with another body is
422 IDEMPOTENCY_KEY_REUSED, and while the first request is still being processed
409 IDEMPOTENCY_KEY_IN_PROGRESS.Query Parameters
boolean
default:"false"
Check only: the same
422 for invalid records, nothing created; 200 with {"dry_run": true, "submitted": n, "valid": n} when every record is valid.Body Parameters
array[object]
required
The vehicles to create, 1 to 1,000. A field not listed here is rejected (
SCHEMA_INVALID).Show record
Show record
string
required
3 to 255 characters, stored as sent (trimmed). It must be free among the organization’s active vehicles and
appear once in the request; plates are compared without spaces, dashes, accents or case, so
1234 ABC and
1234-abc are the same plate.string
required
passenger or freight.string
required
owned (scope 1) or rented (scope 3).string
required
Where the vehicle is used, ISO 3166-1 alpha-2 (
ES, FR…; case-insensitive, returned uppercase). It picks the
emission factors of its consumptions.uuid
required
The vehicle class (passenger car, van, truck…): an
id of
List Unknown Vehicles, other than no_vehicle.array[uuid]
required
The fuels the vehicle runs on, each once; the first is its primary fuel. Each an
id of
List Vehicle Fuels that the vehicle class can run on.string
Your name for the vehicle, up to 255 characters.
integer
Year of registration, from 1900 to the current year.
string
Car market segment:
mini, supermini, lower_medium, upper_medium, executive, luxury, sports,
dual_purpose_4x4 or mpv (see List Market Segments).string
Car size:
small_car, medium, large_car or average_car.uuid
A record of your custom emission factor databases to
calculate its consumptions with, instead of the default: find it with
List Records. Its
activity_categories must include
transport, and the vehicle must have exactly one fuel.string
Your own reference for the record, up to 255 characters, echoed in the answer and in errors.
Response
201 Created with items: one per record, in the order sent, each with source_row_index, client_row_id and the
created vehicle: id, organization_id, license_plate, name, type, ownership, country,
unknown_vehicle_id, vehicle_fuel_ids (primary first), registration_year, market_segment, size, status
(active) and UTC timestamps ending in Z. Its emissions come with its consumptions: there is no co2e here.
Errors
Problem details. Per-record codes inerrors[].error_code:
error_code | Cause |
|---|---|
SCHEMA_INVALID | The record does not match the schema: a missing or unknown field (e.g. organization_id), a plate under 3 characters, a fuel listed twice, a registration_year in the future, custom_ef_record_id with more than one fuel… error_params.errors says where. |
LICENSE_PLATE_ALREADY_EXISTS | An active vehicle of the organization already has this plate (compared without spaces, dashes, accents or case). |
DUPLICATE_LICENSE_PLATE | Another record of the request has the same plate. |
REFERENCE_NOT_FOUND | country, unknown_vehicle_id or a fuel of vehicle_fuel_ids does not exist (error_params.field says which). |
FUEL_NOT_ALLOWED_FOR_VEHICLE_TYPE | A fuel of vehicle_fuel_ids is not one the vehicle class runs on (error_params.value is the fuel). |
MULTIDB_CUSTOM_RECORD_NOT_FOUND_OR_DISABLED | custom_ef_record_id does not exist, is disabled or is not visible from your organization. |
MULTIDB_CUSTOM_RECORD_INCOMPATIBLE_CATEGORY | custom_ef_record_id is not configured for the transport activity category. |
401 for a missing or invalid API key, 403 LOGGED_USER_NOT_MEMBER when the key’s user is not a member of the
organization, 422 REQUEST_VALIDATION_FAILED for a malformed body (no records, more than 1,000, no
Idempotency-Key), 422 IDEMPOTENCY_KEY_REUSED, 409 IDEMPOTENCY_KEY_IN_PROGRESS, and 429 beyond the
rate limits.
Retries and idempotency
- Network error or timeout: retry with the same
Idempotency-Keyand body. If the first request was accepted you get the same vehicles back, withIdempotent-Replayed: true, and nothing is duplicated. 422 BULK_RECORDS_REJECTED: nothing was created. Fix the records and send the batch again.
Limits
| Limit | Value |
|---|---|
| Records per request | 1 to 1,000 |
Related Endpoints
Delete Vehicles (v2)
Delete up to 1,000 vehicles with their consumptions
List Unknown Vehicles
Ids for
unknown_vehicle_idList Vehicle Fuels
Ids for
vehicle_fuel_idsVehicle Consumptions
What the vehicles’ emissions come from
Was this page helpful?