List Units
const options = {
method: 'GET',
headers: {'x-api-key': '<x-api-key>', 'x-organization-id': '<x-organization-id>'}
};
fetch('https://api.dcycle.io/v2/units', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v2/units"
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>"
}
response = requests.get(url, headers=headers)
print(response.text)curl --request GET \
--url https://api.dcycle.io/v2/units \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>'{
"array": {
"id": "<string>",
"name": "<string>",
"type": "<string>"
}
}List Units
Retrieve the unit catalog and resolve the unit ids that invoices, purchases, wastes, shipments and vehicle consumptions expect
GET
/
v2
/
units
List Units
const options = {
method: 'GET',
headers: {'x-api-key': '<x-api-key>', 'x-organization-id': '<x-organization-id>'}
};
fetch('https://api.dcycle.io/v2/units', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v2/units"
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>"
}
response = requests.get(url, headers=headers)
print(response.text)curl --request GET \
--url https://api.dcycle.io/v2/units \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>'{
"array": {
"id": "<string>",
"name": "<string>",
"type": "<string>"
}
}Retrieve the catalog of measurement units. Every endpoint that takes a unit (
Custom emission factors only
These values are used by a single form: the one that creates a
custom emission factor record, which offers these units for the
record’s
Cause: The API key belongs to an organization that is neither the one in
Cause: The API key has no owner, which happens with old keys. Regenerate it.
Cause: No credentials at all: neither
Cause: The API key was sent as
Cause:
unit_id, non_currency_unit_id, …)
expects the id of an entry of this catalog, so this is where you look it up.
Reference data. The catalog is global: the same ids apply to every organization, and the response is not filtered
by the organization you authenticate with. Unit ids do not change, so fetch the catalog once, cache it, and look ids
up locally.
Request
Headers
string
required
Your API key for authentication. Send it in this header: a key sent as
Authorization: Bearer is read as a login
token and rejected with 401.Format: Your API key stringstring
required
UUID of the API key’s organization, or of one of its subsidiaries. Required even though the catalog itself is
global: the key is checked against it.Format: UUID
Query Parameters
string
Optional shortcut to the units the Dcycle app offers in one form, instead of the whole catalog. Each value returns a
fixed list of units, shown in What each type returns. It does not filter on the
type
field of the response, and it does not validate anything.Omit it to get the whole catalog. A value outside the table is rejected with 422. Send it as type: a parameter
named type[] is ignored, so ?type[]=wastes returns the whole catalog.Example: wastesWhat each type returns
Each value is the list of units that one form of the Dcycle app offers. The lists are fixed, not derived from thetype field of the units they contain: type=wastes returns kilogram_(kg), whose type is solid.
Forms for activity data
type | Units returned | Used in the Dcycle app for |
|---|---|---|
vehicle_consumptions | kilogram_(kg), metric_tonne_(t), litre_(l), gallon_(gal), kilowatt_hour_(kwh), kilometer_(km), mile_(mi) | Vehicle consumptions. Also custom factors for transport and transport_generation |
stationary_combustion | Energy: kilowatt_hour_(kwh), megajoule_(mj), gigajoule_(gj), terajoule_(tj), therm_(thm), metric_million_btu_(mmbtu). Volume: litre_(l), gallon_(gal), barrel_(bbl), cubic_metre_(m3), cubic_foot_(ft3). Mass: kilogram_(kg), metric_tonne_(t), pound_(lb). Gross calorific value: kilowatt_hour_gross_(kwh_gross), megajoule_gross_(mj_gross), gigajoule_gross_(gj_gross), terajoule_gross_(tj_gross) | Combustion invoices (heat). Also custom factors for stationary and stationary_generation |
recharge | kilogram_(kg) | Recharge invoices (recharge). Also custom factors for recharge |
water | litre_(l), cubic_metre_(m3), gallon_(gal), kilogram_(kg) | Water invoices (water). Also custom factors for water |
non_currency_purchases | kilogram_(kg), litre_(l), cubic_metre_(m3), meter_(m), square_meter_(m2), hectare_(ha), kilowatt_hour_(kwh), megajoule_(mj), unit product | Physical quantity of a purchase (non_currency_unit_id) |
transport | kilogram_(kg), metric_tonne_(t), pound_(lb) | Weight of a shipment (unit_id of a transport route) |
products | unit product, kilogram_(kg), cubic_metre_(m3), metric_tonne_(t) | Use of sold products: the units of a product |
use_of_product_electricity | kilowatt_hour_(kwh), megawatt_hour_(mwh) | Electricity a sold product uses |
use_of_product_combustion | kilowatt_hour_(kwh), megajoule_(mj), litre_(l), kilogram_(kg), metric_tonne_(t) | Fuel a sold product burns |
use_of_product_water | litre_(l), cubic_metre_(m3), gallon_(gal), kilogram_(kg), metric_tonne_(t) | Water a sold product uses |
use_of_product_fugitive | kilogram_(kg) | Refrigerant gas a sold product leaks |
unit_id depending on its activity category.
type | Units returned | Activity categories |
|---|---|---|
custom_emission_factors_purchases | euros_(eur) plus the non_currency_purchases units | purchases |
electricity | kilowatt_hour_(kwh) | electricity, heat_and_steam and cooling, with their _generation and _transmission_and_distribution categories |
process | kilogram_(kg), metric_tonne_(t), litre_(l), cubic_metre_(m3), meter_(m), square_meter_(m2), kilowatt_hour_(kwh), megajoule_(mj), unit product | process |
travels | kilometer_(km), person_kilometer_(pkm) | travels and employees_in_itinere |
employees_telecommute | hour_(h), day | employees_telecommute |
hotel_stays | room_per_night | hotel_stays |
transport_distribution | ton kilometer_(tkm) | transport_distribution_upstream, transport_distribution_downstream and their wtt_ categories |
wastes | kilogram_(kg) only | wastes |
waste_transport | ton kilometer_(tkm), kilometer_(km) | waste_transport |
type tells you what the app offers, not what an endpoint accepts. Some write endpoints accept only a fixed set
of units and reject any other: the weight of a shipment, for example, must be one of the units type=transport
returns. Others apply their own rules, like vehicle consumptions, which accept the units of the vehicle’s fuel
(List Vehicle Fuels). Check the unit field on the page of the endpoint you write
to.The type of each unit in the response is a different thing: a legacy classification (solid, mass, energy,
fiat_currency, …) that is not a valid value for this parameter. In particular, no value of the parameter returns
the currencies: to resolve one, request the whole catalog and match its name (see
Resolve the currency of a purchase).Response
array[object]
Array of unit objects, not paginated. Without
type, and with type=transport, it is ordered by name; with any
other type the order is not guaranteed. Do not rely on positions either way: pick a unit by id or by its exact
name.Show Unit Object
Show Unit Object
string
Unit id (UUID). This is the value to send as
unit_id. It does not change, so you can store the ones you use.string
Unit name, in snake_case with its symbol or ISO code in parentheses:
kilogram_(kg), kilowatt_hour_(kwh),
euros_(eur). The symbol keeps its own casing (giga_british_thermal_unit_(GBTU)), and some names do not follow
the pattern at all (unit product, ton kilometer_(tkm), room_per_night, day).Compare the exact name, never a prefix: many names start with kilogram, from kilogram_(kg) to
kilogram_(kg) material and kilograms_co2_(kg_co2). A few names belong to two units (kilogram_day_(kg_day)
is one); for those, use the id.string
Legacy classification stored with each unit. It is not reliable for filtering:
kilogram_(kg) is solid,
kilometer_(km) and cubic_metre_(m3) are gas, and imperial_gallon_(gal_imp) is mass. Identify units by
id or exact name instead. The one dependable value is fiat_currency, which marks the currencies.Example
# Whole catalog
curl -X GET "https://api.dcycle.io/v2/units" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-organization-id: YOUR_ORGANIZATION_ID"
# Only the weight units of a shipment
curl -X GET "https://api.dcycle.io/v2/units?type=transport" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-organization-id: YOUR_ORGANIZATION_ID"
import requests
response = requests.get(
"https://api.dcycle.io/v2/units",
headers={
"x-api-key": "YOUR_API_KEY",
"x-organization-id": "YOUR_ORGANIZATION_ID",
},
timeout=30,
)
response.raise_for_status()
units = response.json()
# Resolve the units you need once, by exact name, then reuse the ids
kilogram = next(u for u in units if u["name"] == "kilogram_(kg)")
euro = next(u for u in units if u["name"] == "euros_(eur)")
print(kilogram["id"]) # 61743a63-ff70-459c-9567-5eee8f7dfd5c
print(euro["id"]) # d3e37f2b-0fc3-4532-82f8-3890ab56ad37
const response = await fetch("https://api.dcycle.io/v2/units", {
headers: {
"x-api-key": "YOUR_API_KEY",
"x-organization-id": "YOUR_ORGANIZATION_ID",
},
});
const units = await response.json();
const kilogram = units.find((u) => u.name === "kilogram_(kg)");
console.log(kilogram.id); // 61743a63-ff70-459c-9567-5eee8f7dfd5c
Successful Response
Returns200 OK with the unit array. For ?type=transport:
[
{
"id": "61743a63-ff70-459c-9567-5eee8f7dfd5c",
"name": "kilogram_(kg)",
"type": "solid"
},
{
"id": "cab66828-c2b1-431b-92af-f9ab37149d3c",
"name": "metric_tonne_(t)",
"type": "solid"
},
{
"id": "7ef7e667-4b45-4130-b46b-785b1604742a",
"name": "pound_(lb)",
"type": "solid"
}
]
Common Errors
Errors on this endpoint use the{"code", "detail"} and {"detail": [...]} shapes below, not the problem details
format of /v2/wastes.
401 Unauthorized
Cause: The API key does not exist or is not active.{
"code": "INVALID_API_KEY",
"detail": "Invalid API key"
}
x-organization-id nor one of its parents.
{
"code": "API_KEY_ORG_MISMATCH",
"detail": "API key does not belong to this organization or any of its parents"
}
{
"code": "API_KEY_NO_OWNER",
"detail": "Legacy API key without owner; please regenerate your API key"
}
x-api-key nor a login token.
{
"code": "CREDENTIALS_REQUIRED",
"detail": "Credentials required (API key or JWT token)"
}
Authorization: Bearer. That header is for login tokens, so the key is rejected
before it is checked. Send it in x-api-key.
{
"detail": "INVALID_OR_EXPIRED_TOKEN"
}
403 Forbidden
Cause: The user who created the API key is not an active member of the organization inx-organization-id.
{
"code": "LOGGED_USER_NOT_MEMBER",
"detail": "Logged User is not Member of Organization"
}
404 Not Found
Cause: No organization has the id inx-organization-id. This is checked before the API key.
{
"code": "ORGANIZATION_NOT_FOUND",
"detail": "Organization with id=UUID('3fa85f64-5717-4562-b3fc-2c963f66afa6') not found"
}
422 Unprocessable Entity
Cause:x-organization-id is missing. The catalog is global, but the header is still required. A value that is not
a UUID fails the same way, with "msg": "value is not a valid uuid".
{
"detail": [
{
"loc": ["header", "x-organization-id"],
"msg": "field required",
"type": "value_error.missing"
}
]
}
type is not one of the values in What each type returns. The type values you
read in a response (solid, mass, fiat_currency, …) are not accepted here.
{
"detail": [
{
"loc": ["query", "type"],
"msg": "value is not a valid enumeration member; permitted: 'vehicle_consumptions', 'products', 'use_of_product_combustion', 'use_of_product_electricity', 'use_of_product_water', 'use_of_product_fugitive', 'custom_emission_factors_purchases', 'stationary_combustion', 'recharge', 'water', 'non_currency_purchases', 'electricity', 'process', 'travels', 'transport_distribution', 'transport', 'wastes', 'waste_transport', 'hotel_stays', 'employees_telecommute'",
"type": "type_error.enum",
"ctx": {
"enum_values": [
"vehicle_consumptions",
"products",
"use_of_product_combustion",
"use_of_product_electricity",
"use_of_product_water",
"use_of_product_fugitive",
"custom_emission_factors_purchases",
"stationary_combustion",
"recharge",
"water",
"non_currency_purchases",
"electricity",
"process",
"travels",
"transport_distribution",
"transport",
"wastes",
"waste_transport",
"hotel_stays",
"employees_telecommute"
]
}
}
]
}
Use Cases
Resolve the currency of a purchase
A purchase takesunit_id as the currency of its amount, and non_currency_unit_id as the physical unit when you
track quantity instead (the units of type=non_currency_purchases). No value of the type parameter returns the
currencies: request the whole catalog and match the currency’s name, which ends with its ISO code in parentheses
(euros_(eur), us_dollar_(usd), british_pound_(gbp)). Currencies are the entries whose type is fiat_currency.
euro_id = next(u["id"] for u in units if u["name"] == "euros_(eur)")
requests.post(
"https://api.dcycle.io/v1/purchases",
headers={"x-api-key": KEY, "x-organization-id": ORG},
json={
"expense_type": "opex", # "capex" or "opex"
"product_name": "Office paper",
"purchase_date": "2026-01-31",
"quantity": 1500.0,
"unit_id": euro_id,
},
timeout=30,
)
expense_type, product_name and purchase_date are required, and the schema rejects unknown fields — so a date
key instead of purchase_date fails validation rather than being ignored.
Offer your users the units the app offers
When your own users pick a unit, request the list for the matching form (type=water, type=stationary_combustion, …)
and offer those: they are the units the Dcycle app offers in the same form. This does not replace the checks of the
endpoint you write to: type validates nothing, and each write endpoint decides which units it accepts.
Related Endpoints
Create Purchase
Takes the currency as
unit_id and the physical unit as non_currency_unit_idCreate Invoice
Takes
unit_id for the consumption in base_quantityList LER Codes
LER code catalog: the
waste_ler_code_id of a wasteList R/D Codes
Treatment code catalog: the
waste_rd_code_id of a wasteList Vehicle Fuels
Fuel catalog, with the units accepted for each fuel
Create Transport Route
Takes the weight of a shipment as
unit_id, one of the type=transport unitsWas this page helpful?