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

> Get a list of measurement units available in Dcycle

# List Units

Retrieve all measurement units available in the Dcycle system. These units are used when creating invoices, purchases, and other consumption records to specify quantities.

<Note>
  Units are **reference data** maintained by Dcycle. You cannot create or modify units through the API - this endpoint is read-only.
</Note>

## Request

### Headers

<ParamField header="x-api-key" type="string" required>
  Your API key for authentication

  **Example:** `sk_live_1234567890abcdef`
</ParamField>

<ParamField header="x-organization-id" type="string" required>
  Your organization UUID

  **Example:** `ff4adcc7-8172-45fe-9cf1-e90a6de53aa9`
</ParamField>

<ParamField header="x-user-id" type="string" required>
  Your user UUID

  **Example:** `a1b2c3d4-e5f6-7890-abcd-ef1234567890`
</ParamField>

### Query Parameters

<ParamField query="type" type="string">
  Filter units by type category

  **Valid values:**

  * `energy` - Energy units (kWh, MWh, GJ, etc.)
  * `gas` - Gas volume units (m³, ft³, etc.)
  * `liquid` - Liquid volume units (L, m³, gal, etc.)
  * `solid` - Solid mass/volume units (kg, ton, m³, etc.)
  * `fiat_currency` - Currency units (EUR, USD, etc.)
  * `dimensionless` - Unitless quantities
  * `substance` - Chemical substance units
  * `waste_water_treatment_dbo` - Biochemical oxygen demand
  * `waste_water_treatment_dbo_out` - BOD output measurements
  * `waste_water_treatment_ch4` - Methane measurements
  * `waste_water_treatment_nitrogen` - Nitrogen measurements
  * `waste_water_treatments_flow_total` - Flow rate measurements
  * `area_time` - Area-time combined units
  * `toxicity` - Toxicity measurements
  * `radioactivity` - Radioactivity measurements
  * `purchases_supplier_specific` - Supplier-specific purchase units

  **Example:** `"energy"`
</ParamField>

## Response

Returns an array of unit objects (not paginated - all matching units are returned).

<ResponseField name="[]" type="array">
  Array of unit objects

  ### Unit Object Fields:

  <ResponseField name="id" type="string">
    Unique unit identifier (UUID v4)
  </ResponseField>

  <ResponseField name="name" type="string">
    Human-readable unit name (e.g., "kWh", "m³", "kg")
  </ResponseField>

  <ResponseField name="type" type="string">
    Unit type category (see valid values above)
  </ResponseField>
</ResponseField>

## Example

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X GET "https://api.dcycle.io/api/v1/units?type=energy" \
    -H "Authorization: Bearer ${DCYCLE_API_KEY}" \
    -H "x-organization-id: ${DCYCLE_ORG_ID}" \
    -H "x-user-id: ${DCYCLE_USER_ID}"
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests
  import os

  api_key = os.getenv("DCYCLE_API_KEY")
  org_id = os.getenv("DCYCLE_ORG_ID")
  user_id = os.getenv("DCYCLE_USER_ID")

  headers = {
      "Authorization": f"Bearer {api_key}",
      "x-organization-id": org_id,
      "x-user-id": user_id
  }

  # Get all energy units
  params = {"type": "energy"}

  response = requests.get(
      "https://api.dcycle.io/api/v1/units",
      headers=headers,
      params=params
  )

  units = response.json()
  print(f"Found {len(units)} energy units:")

  for unit in units:
      print(f"- {unit['name']} (ID: {unit['id']})")
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const axios = require('axios');

  const apiKey = process.env.DCYCLE_API_KEY;
  const orgId = process.env.DCYCLE_ORG_ID;
  const userId = process.env.DCYCLE_USER_ID;

  const headers = {
    'Authorization': `Bearer ${apiKey}`,
    'x-organization-id': orgId,
    'x-user-id': userId
  };

  // Get all energy units
  const params = { type: 'energy' };

  axios.get('https://api.dcycle.io/api/v1/units', { headers, params })
    .then(response => {
      const units = response.data;
      console.log(`Found ${units.length} energy units:`);

      units.forEach(unit => {
        console.log(`- ${unit.name} (ID: ${unit.id})`);
      });
    })
    .catch(error => console.error(error));
  ```
</CodeGroup>

### Successful Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "kWh",
    "type": "energy"
  },
  {
    "id": "b2c3d4e5-f6g7-8901-bcde-fg2345678901",
    "name": "MWh",
    "type": "energy"
  },
  {
    "id": "c3d4e5f6-g7h8-9012-cdef-gh3456789012",
    "name": "GJ",
    "type": "energy"
  },
  {
    "id": "d4e5f6g7-h8i9-0123-defg-hi4567890123",
    "name": "kWh HHV",
    "type": "energy"
  }
]
```

## Common Errors

### 400 Bad Request - Invalid Type

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": "Invalid unit type",
  "code": "VALIDATION_ERROR"
}
```

**Solution:** Verify that the `type` parameter matches one of the valid values listed above.

### 403 Forbidden

**Cause:** Organization ID doesn't match your API key or user doesn't belong to organization

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": "Not authorized",
  "code": "FORBIDDEN"
}
```

**Solution:** Verify that `x-organization-id` matches your API key's organization.

## Use Cases

### Get Energy Units for Invoice Creation

When creating an invoice, you need the unit ID for the `base_quantity` field:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def get_energy_units():
    """Get all energy units available"""
    response = requests.get(
        "https://api.dcycle.io/api/v1/units",
        headers=headers,
        params={"type": "energy"}
    )

    units = response.json()

    # Create lookup dictionary
    units_by_name = {unit['name']: unit['id'] for unit in units}

    return units_by_name

# Usage: Get kWh unit ID for invoice
energy_units = get_energy_units()
kwh_unit_id = energy_units.get('kWh')

# Now create invoice with this unit
invoice_data = {
    "type": "electricity",
    "base_quantity": 15000.0,
    "unit_id": kwh_unit_id,
    "start_date": "2024-01-01",
    "end_date": "2024-01-31",
    "uploaded_by": "energy_manager",
    "facility_percentages": [
        {
            "facility_id": "facility-uuid-here",
            "percentage": 1.0
        }
    ]
}

requests.post(
    "https://api.dcycle.io/api/v1/invoices",
    headers=headers,
    json=invoice_data
)
```

### Get All Units for Dropdown Selector

Build a complete unit selector for your application:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def get_all_units():
    """Get all units organized by type"""
    response = requests.get(
        "https://api.dcycle.io/api/v1/units",
        headers=headers
    )

    all_units = response.json()

    # Organize by type
    units_by_type = {}
    for unit in all_units:
        unit_type = unit['type']
        if unit_type not in units_by_type:
            units_by_type[unit_type] = []
        units_by_type[unit_type].append(unit)

    return units_by_type

# Usage
units = get_all_units()
print(f"Available unit types: {list(units.keys())}")
print(f"Energy units: {[u['name'] for u in units.get('energy', [])]}")
print(f"Gas units: {[u['name'] for u in units.get('gas', [])]}")
```

### Cache Units for Performance

Since units are reference data that rarely changes, cache them:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import functools
from datetime import datetime, timedelta

class DcycleUnitsCache:
    def __init__(self, api_key, org_id, user_id):
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "x-organization-id": org_id,
            "x-user-id": user_id
        }
        self._cache = {}
        self._cache_time = None
        self.cache_duration = timedelta(hours=24)

    def get_units(self, unit_type=None):
        """Get units with caching"""
        # Check if cache is valid
        if (self._cache_time is None or
            datetime.now() - self._cache_time > self.cache_duration):
            self._refresh_cache()

        # Return cached data
        if unit_type:
            return [u for u in self._cache.values() if u['type'] == unit_type]
        return list(self._cache.values())

    def _refresh_cache(self):
        """Refresh the cache"""
        response = requests.get(
            "https://api.dcycle.io/api/v1/units",
            headers=self.headers
        )

        units = response.json()
        self._cache = {unit['id']: unit for unit in units}
        self._cache_time = datetime.now()

        print(f"✅ Units cache refreshed: {len(self._cache)} units loaded")

    def get_unit_by_id(self, unit_id):
        """Get a specific unit by ID"""
        if unit_id not in self._cache:
            self._refresh_cache()
        return self._cache.get(unit_id)

    def get_unit_by_name(self, name, unit_type=None):
        """Get a unit by name"""
        units = self.get_units(unit_type)
        for unit in units:
            if unit['name'].lower() == name.lower():
                return unit
        return None

# Usage
cache = DcycleUnitsCache(
    api_key=os.getenv("DCYCLE_API_KEY"),
    org_id=os.getenv("DCYCLE_ORG_ID"),
    user_id=os.getenv("DCYCLE_USER_ID")
)

# First call fetches from API
kwh_unit = cache.get_unit_by_name("kWh", "energy")

# Subsequent calls use cache (no API request)
mwh_unit = cache.get_unit_by_name("MWh", "energy")
```

## Unit Types Breakdown

### Most Common Types

**Energy Units** (`type: "energy"`):

* Used for electricity invoices
* Common units: kWh, MWh, GJ, kWh HHV, kWh LHV
* Example: Electricity consumption from utility bills

**Gas Units** (`type: "gas"`):

* Used for natural gas, propane, other gaseous fuels
* Common units: m³, ft³, Nm³
* Example: Natural gas heating consumption

**Liquid Units** (`type: "liquid"`):

* Used for liquid fuels (diesel, gasoline, etc.)
* Common units: L, m³, gal, bbl
* Example: Diesel fuel for generators

**Solid Units** (`type: "solid"`):

* Used for solid fuels and materials
* Common units: kg, ton, tonne, lb
* Example: Coal, biomass, waste materials

### Specialized Types

**Waste Water Treatment Units**:

* `waste_water_treatment_dbo` - Biochemical oxygen demand input
* `waste_water_treatment_dbo_out` - BOD after treatment
* `waste_water_treatment_ch4` - Methane emissions from treatment
* `waste_water_treatment_nitrogen` - Nitrogen content
* `waste_water_treatments_flow_total` - Total flow rate

**Other Specialized Units**:

* `fiat_currency` - For financial calculations (EUR, USD, etc.)
* `purchases_supplier_specific` - Custom units from suppliers
* `substance` - Chemical substances (kg CO2, kg NOx, etc.)
* `dimensionless` - Ratios, percentages, counts
* `toxicity` - Toxicity equivalents
* `radioactivity` - Radioactive measurements

## Best Practices

### 1. Cache Reference Data

Since units don't change frequently, cache them in your application:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Good - Cache for 24 hours
units_cache = cache.get_units()

# Bad - Fetch every time you need a unit
unit = requests.get(f"https://api.dcycle.io/api/v1/units?type=energy")
```

### 2. Use Type Filtering

Filter by type when you know the invoice category:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Good - Only fetch energy units
energy_units = get_units(type="energy")

# Less efficient - Fetch all and filter client-side
all_units = get_units()
energy_units = [u for u in all_units if u['type'] == 'energy']
```

### 3. Store Unit IDs in Configuration

For common units, store their IDs in your configuration:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# config.py
COMMON_UNITS = {
    'kwh': 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
    'mwh': 'b2c3d4e5-f6g7-8901-bcde-fg2345678901',
    'm3_gas': 'c3d4e5f6-g7h8-9012-cdef-gh3456789012',
    'liters': 'd4e5f6g7-h8i9-0123-defg-hi4567890123'
}

# Usage - No API call needed
invoice_data = {
    "unit_id": COMMON_UNITS['kwh'],
    # ... other fields
}
```

### 4. Validate Units Before Invoice Creation

Check that the unit type matches the invoice type:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def validate_unit_for_invoice(unit_id, invoice_type):
    """Validate that unit matches invoice type"""

    # Define valid unit types for each invoice type
    valid_units = {
        'electricity': ['energy'],
        'heat': ['energy', 'gas'],
        'water': ['liquid'],
        'recharge': ['energy'],  # Electric vehicle charging
        'process': ['energy', 'gas', 'liquid', 'solid'],
        'wastes': ['solid', 'liquid'],
        'waste_water_treatment': [
            'waste_water_treatment_dbo',
            'waste_water_treatment_nitrogen',
            'waste_water_treatments_flow_total'
        ]
    }

    # Get unit details
    unit = cache.get_unit_by_id(unit_id)

    if unit['type'] not in valid_units.get(invoice_type, []):
        raise ValueError(
            f"Unit type '{unit['type']}' is not valid for invoice type '{invoice_type}'"
        )

    return True
```

## Related Endpoints

<CardGroup cols={2}>
  <Card title="Create Invoice" icon="file-invoice" href="/api-docs/invoices/create">
    Create invoices using unit IDs
  </Card>

  <Card title="List Invoices" icon="list" href="/api-docs/invoices/list">
    View invoices with their units
  </Card>

  <Card title="List Suppliers" icon="truck" href="/api-docs/suppliers/list">
    Get suppliers for invoices
  </Card>

  <Card title="Authentication" icon="key" href="/api-docs/authentication">
    Learn about API authentication
  </Card>
</CardGroup>
