> ## 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.

# List Units

> Retrieve the unit catalog and resolve the unit ids that invoices, purchases, wastes, shipments and vehicle consumptions expect

Retrieve the catalog of measurement units. Every endpoint that takes a unit (`unit_id`, `non_currency_unit_id`, …)
expects the id of an entry of this catalog, so this is where you look it up.

<Note>
  **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.
</Note>

## Request

### Headers

<ParamField header="x-api-key" type="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 string
</ParamField>

<ParamField header="x-organization-id" type="string" 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
</ParamField>

### Query Parameters

<ParamField query="type" type="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](#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:** `wastes`
</ParamField>

### What 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 the
`type` 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 |

**Custom emission factors only**

These values are used by a single form: the one that creates a
[custom emission factor record](/api-reference/custom-emission-factors/create-record), which offers these units for the
record's `unit_id` depending on its [activity category](/api-reference/custom-emission-factors/overview#activity-categories).

| `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` |

<Warning>
  **`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](/api-reference/vehicle-fuels/list)). 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](#resolve-the-currency-of-a-purchase)).
</Warning>

## Response

<ResponseField name="array" type="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`.

  <Expandable title="Unit Object">
    <ResponseField name="id" type="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.
    </ResponseField>

    <ResponseField name="name" type="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`.
    </ResponseField>

    <ResponseField name="type" type="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.
    </ResponseField>
  </Expandable>
</ResponseField>

## Example

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  # 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"
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  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
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  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
  ```
</CodeGroup>

### Successful Response

Returns `200 OK` with the unit array. For `?type=transport`:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
[
  {
    "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`](/api-reference/wastes/create-v2).

### 401 Unauthorized

**Cause:** The API key does not exist or is not active.

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

**Cause:** The API key belongs to an organization that is neither the one in `x-organization-id` nor one of its parents.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "code": "API_KEY_ORG_MISMATCH",
  "detail": "API key does not belong to this organization or any of its parents"
}
```

**Cause:** The API key has no owner, which happens with old keys. Regenerate it.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "code": "API_KEY_NO_OWNER",
  "detail": "Legacy API key without owner; please regenerate your API key"
}
```

**Cause:** No credentials at all: neither `x-api-key` nor a login token.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "code": "CREDENTIALS_REQUIRED",
  "detail": "Credentials required (API key or JWT token)"
}
```

**Cause:** The API key was sent as `Authorization: Bearer`. That header is for login tokens, so the key is rejected
before it is checked. Send it in `x-api-key`.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": "INVALID_OR_EXPIRED_TOKEN"
}
```

### 403 Forbidden

**Cause:** The user who created the API key is not an active member of the organization in `x-organization-id`.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "code": "LOGGED_USER_NOT_MEMBER",
  "detail": "Logged User is not Member of Organization"
}
```

### 404 Not Found

**Cause:** No organization has the id in `x-organization-id`. This is checked before the API key.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "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"`.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": [
    {
      "loc": ["header", "x-organization-id"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

**Cause:** `type` is not one of the values in [What each type returns](#what-each-type-returns). The `type` values you
read in a response (`solid`, `mass`, `fiat_currency`, …) are not accepted here.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "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 takes `unit_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`.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
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

<CardGroup cols={2}>
  <Card title="Create Purchase" icon="cart-shopping" href="/api-reference/purchases/create">
    Takes the currency as `unit_id` and the physical unit as `non_currency_unit_id`
  </Card>

  <Card title="Create Invoice" icon="file-invoice" href="/api-reference/invoices/create">
    Takes `unit_id` for the consumption in `base_quantity`
  </Card>

  <Card title="List LER Codes" icon="recycle" href="/api-reference/wastes/ler-codes">
    LER code catalog: the `waste_ler_code_id` of a waste
  </Card>

  <Card title="List R/D Codes" icon="recycle" href="/api-reference/wastes/rd-codes">
    Treatment code catalog: the `waste_rd_code_id` of a waste
  </Card>

  <Card title="List Vehicle Fuels" icon="gas-pump" href="/api-reference/vehicle-fuels/list">
    Fuel catalog, with the units accepted for each fuel
  </Card>

  <Card title="Create Transport Route" icon="truck" href="/api-reference/transport/create">
    Takes the weight of a shipment as `unit_id`, one of the `type=transport` units
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.