Skip to main content
GET
https://api.dcycle.io
/
api
/
v1
/
facility_fuels
List Facility Fuels
const options = {
  method: 'GET',
  headers: {
    'x-api-key': '<x-api-key>',
    'x-organization-id': '<x-organization-id>',
    'x-user-id': '<x-user-id>'
  }
};

fetch('https://api.dcycle.io/api/v1/facility_fuels', options)
  .then(res => res.json())
  .then(res => console.log(res))
  .catch(err => console.error(err));
{
  "[]": [
    {
      "id": "<string>",
      "name": "<string>",
      "country": "<string>",
      "type": "<string>",
      "ghg_type": 123,
      "units": [
        {}
      ]
    }
  ]
}

List Facility Fuels

Retrieve all facility fuels available in the Dcycle system. Facility fuels represent different types of energy sources consumed at facilities (natural gas, diesel, heating oil, LPG, etc.) and are used when creating process-type invoices.
Facility fuels are reference data maintained by Dcycle. You cannot create or modify fuels through the API - this endpoint is read-only.

Request

Headers

x-api-key
string
required
Your API key for authenticationExample: sk_live_1234567890abcdef
x-organization-id
string
required
Your organization UUIDExample: ff4adcc7-8172-45fe-9cf1-e90a6de53aa9
x-user-id
string
required
Your user UUIDExample: a1b2c3d4-e5f6-7890-abcd-ef1234567890

Query Parameters

country
string
Filter facility fuels by country using ISO 3166-1 alpha-2 country codeSupported country codes:
  • ES - Spain (returns Spanish facility fuels)
  • Any other code returns generic GHG database fuels
Country-specific facility fuels are currently only available for Spain (ES). Other countries will receive generic fuels from the GHG Protocol database.
Example: "ES"

Response

Returns an array of facility fuel objects (not paginated - all matching fuels are returned).
[]
array
Array of facility fuel objects

Facility Fuel Object Fields:

id
string
Unique fuel identifier (UUID v4)
name
string
Fuel name (e.g., “Natural gas”, “Diesel”, “Propane”, “Heating oil”)
country
string
ISO 3166-1 alpha-2 country code where fuel data applies
type
string
Fuel type classification (e.g., “gas”, “liquid”, “solid”)
ghg_type
integer
GHG type classification for emissions calculationsCommon values:
  • 1 - Fossil fuels
  • 2 - Biofuels
  • 3 - Mixed sources
units
array
Array of available measurement units for this fuelEach unit object contains:
  • id (string) - Unit UUID
  • name (string) - Unit name (e.g., “m³”, “L”, “kWh”)
  • type (string) - Unit type (e.g., “gas”, “liquid”, “energy”)

Example

curl -X GET "https://api.dcycle.io/api/v1/facility_fuels?country=ES" \
  -H "Authorization: Bearer ${DCYCLE_API_KEY}" \
  -H "x-organization-id: ${DCYCLE_ORG_ID}" \
  -H "x-user-id: ${DCYCLE_USER_ID}"

Successful Response

[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Natural gas",
    "country": "ES",
    "type": "gas",
    "ghg_type": 1,
    "units": [
      {
        "id": "unit-1-uuid",
        "name": "m³",
        "type": "gas"
      },
      {
        "id": "unit-2-uuid",
        "name": "kWh",
        "type": "energy"
      },
      {
        "id": "unit-3-uuid",
        "name": "kWh HHV",
        "type": "energy"
      }
    ]
  },
  {
    "id": "b2c3d4e5-f6g7-8901-bcde-fg2345678901",
    "name": "Diesel",
    "country": "ES",
    "type": "liquid",
    "ghg_type": 1,
    "units": [
      {
        "id": "unit-4-uuid",
        "name": "L",
        "type": "liquid"
      },
      {
        "id": "unit-5-uuid",
        "name": "kWh",
        "type": "energy"
      }
    ]
  },
  {
    "id": "c3d4e5f6-g7h8-9012-cdef-gh3456789012",
    "name": "Propane (LPG)",
    "country": "ES",
    "type": "gas",
    "ghg_type": 1,
    "units": [
      {
        "id": "unit-6-uuid",
        "name": "kg",
        "type": "solid"
      },
      {
        "id": "unit-7-uuid",
        "name": "L",
        "type": "liquid"
      }
    ]
  }
]

Common Errors

400 Bad Request - Invalid Country Code

{
  "detail": "Invalid country code format",
  "code": "VALIDATION_ERROR"
}
Solution: Use a valid ISO 3166-1 alpha-2 country code (2 letters, e.g., “ES”, “FR”, “DE”).

403 Forbidden

Cause: Organization ID doesn’t match your API key or user doesn’t belong to organization
{
  "detail": "Not authorized",
  "code": "FORBIDDEN"
}
Solution: Verify that x-organization-id matches your API key’s organization.

Use Cases

Create Process Invoice with Facility Fuel

When creating a process invoice for fuel consumption at a facility:
def create_natural_gas_invoice(facility_id, consumption_m3):
    """Create invoice for natural gas consumption"""

    # 1. Get Spanish facility fuels
    response = requests.get(
        "https://api.dcycle.io/api/v1/facility_fuels",
        headers=headers,
        params={"country": "ES"}
    )

    fuels = response.json()

    # 2. Find natural gas fuel
    natural_gas = next(
        (f for f in fuels if "Natural gas" in f['name']),
        None
    )

    if not natural_gas:
        print("⚠️ Natural gas fuel not found")
        return

    # 3. Find m³ unit for this fuel
    m3_unit = next(
        (u for u in natural_gas['units'] if u['name'] == 'm³'),
        None
    )

    if not m3_unit:
        print("⚠️ m³ unit not available for natural gas")
        return

    # 4. Create process invoice
    invoice_data = {
        "type": "process",
        "base_quantity": consumption_m3,
        "unit_id": m3_unit['id'],
        "facility_fuel_id": natural_gas['id'],  # Critical: Include fuel ID
        "start_date": "2024-01-01",
        "end_date": "2024-01-31",
        "uploaded_by": "facility_manager",
        "facility_percentages": [
            {
                "facility_id": facility_id,
                "percentage": 1.0
            }
        ]
    }

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

    print(f"✅ Natural gas invoice created: {consumption_m3} m³")
    return response.json()

# Usage: Register 15,000 m³ of natural gas consumption
create_natural_gas_invoice(
    facility_id="facility-uuid",
    consumption_m3=15000.0
)

Build Fuel Selector by Type

Create a UI selector organized by fuel type:
def get_fuels_by_type(country_code):
    """Get facility fuels organized by type"""

    response = requests.get(
        "https://api.dcycle.io/api/v1/facility_fuels",
        headers=headers,
        params={"country": country_code}
    )

    fuels = response.json()

    # Organize by type
    fuels_by_type = {}
    for fuel in fuels:
        fuel_type = fuel['type']
        if fuel_type not in fuels_by_type:
            fuels_by_type[fuel_type] = []

        fuels_by_type[fuel_type].append({
            'id': fuel['id'],
            'name': fuel['name'],
            'units': fuel['units']
        })

    return fuels_by_type

# Usage
fuels = get_fuels_by_type("ES")

print("Gas fuels:")
for fuel in fuels.get('gas', []):
    print(f"  - {fuel['name']}")

print("\nLiquid fuels:")
for fuel in fuels.get('liquid', []):
    print(f"  - {fuel['name']}")

print("\nSolid fuels:")
for fuel in fuels.get('solid', []):
    print(f"  - {fuel['name']}")

Cache Fuels with Units

Cache facility fuels and their units for performance:
from datetime import datetime, timedelta

class DcycleFacilityFuelsCache:
    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 = {}
        self.cache_duration = timedelta(hours=24)

    def get_fuels(self, country=None):
        """Get facility fuels with caching"""

        cache_key = country or 'all'

        # Check if cache is valid
        if (cache_key not in self._cache_time or
            datetime.now() - self._cache_time[cache_key] > self.cache_duration):
            self._refresh_cache(country)

        return self._cache.get(cache_key, [])

    def _refresh_cache(self, country=None):
        """Refresh the cache for a specific country"""

        params = {"country": country} if country else {}

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

        fuels = response.json()

        cache_key = country or 'all'
        self._cache[cache_key] = fuels
        self._cache_time[cache_key] = datetime.now()

        print(f"✅ Facility fuels cache refreshed for '{cache_key}': {len(fuels)} fuels")

    def get_fuel_by_id(self, fuel_id, country=None):
        """Get a specific fuel by ID"""

        fuels = self.get_fuels(country)

        for fuel in fuels:
            if fuel['id'] == fuel_id:
                return fuel

        return None

    def get_fuel_by_name(self, name, country=None):
        """Get a fuel by name (case-insensitive partial match)"""

        fuels = self.get_fuels(country)

        for fuel in fuels:
            if name.lower() in fuel['name'].lower():
                return fuel

        return None

    def get_unit_for_fuel(self, fuel_id, unit_name, country=None):
        """Get a specific unit for a fuel"""

        fuel = self.get_fuel_by_id(fuel_id, country)

        if not fuel:
            return None

        for unit in fuel.get('units', []):
            if unit['name'].lower() == unit_name.lower():
                return unit

        return None

# Usage
cache = DcycleFacilityFuelsCache(
    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
natural_gas = cache.get_fuel_by_name("Natural gas", "ES")
m3_unit = cache.get_unit_for_fuel(natural_gas['id'], "m³", "ES")

# Subsequent calls use cache (no API request)
diesel = cache.get_fuel_by_name("Diesel", "ES")

Validate Unit Compatibility

Ensure selected unit is valid for the chosen fuel:
def validate_unit_for_fuel(fuel_id, unit_id, country):
    """Validate that a unit is available for a specific fuel"""

    # Get fuel details
    response = requests.get(
        "https://api.dcycle.io/api/v1/facility_fuels",
        headers=headers,
        params={"country": country}
    )

    fuels = response.json()

    # Find fuel
    fuel = next((f for f in fuels if f['id'] == fuel_id), None)

    if not fuel:
        raise ValueError(f"Fuel {fuel_id} not found")

    # Check if unit is available for this fuel
    unit_ids = [u['id'] for u in fuel['units']]

    if unit_id not in unit_ids:
        available_units = [u['name'] for u in fuel['units']]
        raise ValueError(
            f"Unit {unit_id} is not valid for fuel '{fuel['name']}'. "
            f"Available units: {', '.join(available_units)}"
        )

    return True

# Usage
try:
    validate_unit_for_fuel(
        fuel_id="natural-gas-uuid",
        unit_id="m3-unit-uuid",
        country="ES"
    )
    print("✅ Unit is valid for this fuel")
except ValueError as e:
    print(f"❌ Validation error: {e}")

Match Fuel Name from Invoice

If you have invoices with fuel names that need to be matched:
def match_fuel_name(invoice_fuel_name, country):
    """Match an invoice fuel name to Dcycle fuel ID"""

    # Get fuels for country
    response = requests.get(
        "https://api.dcycle.io/api/v1/facility_fuels",
        headers=headers,
        params={"country": country}
    )

    fuels = response.json()

    # Normalize invoice name
    normalized_name = invoice_fuel_name.lower().strip()

    # Try exact match first
    for fuel in fuels:
        if fuel['name'].lower() == normalized_name:
            return fuel['id']

    # Try partial match
    for fuel in fuels:
        if normalized_name in fuel['name'].lower():
            return fuel['id']

    # Try reverse partial match
    for fuel in fuels:
        if fuel['name'].lower() in normalized_name:
            return fuel['id']

    # Try fuzzy matching for common variations
    fuel_aliases = {
        'gas natural': 'Natural gas',
        'gasoleo': 'Diesel',
        'gas oil': 'Diesel',
        'glp': 'Propane (LPG)',
        'fuel oil': 'Heating oil'
    }

    for alias, standard_name in fuel_aliases.items():
        if alias in normalized_name:
            for fuel in fuels:
                if standard_name.lower() in fuel['name'].lower():
                    return fuel['id']

    # No match found
    print(f"⚠️ Could not match fuel: '{invoice_fuel_name}'")
    return None

# Usage examples
fuel_names = [
    "Gas Natural",
    "Gasoleo C",
    "GLP Granel"
]

for name in fuel_names:
    fuel_id = match_fuel_name(name, "ES")
    if fuel_id:
        print(f"✅ Matched '{name}' → {fuel_id}")

Country-Specific Behavior

Spain (ES)

Spain has a comprehensive database of facility fuels including:
  • Natural gas - With m³ and kWh units
  • Diesel - For generators and heating
  • Heating oil - For industrial heating
  • Propane (LPG) - For cooking and heating
  • Biomass fuels - Wood pellets, chips
  • Coal - For industrial processes
Spanish facility fuels include country-specific emission factors based on national regulations.

Other Countries

For countries other than Spain, the system returns generic fuels from the GHG Protocol database. These use standard emission factors suitable for:
  • Initial carbon footprint calculations
  • Countries where fuel-specific data is not yet available
  • Approximate emissions estimates
If you need country-specific facility fuels beyond Spain, contact Dcycle support. We’re continuously expanding our fuel databases.

Fuel Types

The type field indicates the physical state of the fuel:
TypeDescriptionExamples
gasGaseous fuelsNatural gas, propane, butane
liquidLiquid fuelsDiesel, heating oil, gasoline
solidSolid fuelsCoal, biomass, wood pellets
energyEnergy-basedElectricity, steam, heat

GHG Types

The ghg_type field classifies fuels for emissions calculations:
GHG TypeDescriptionBiogenic CO2 Treatment
1Fossil fuelsAll CO2 counted as emissions
2BiofuelsBiogenic CO2 reported separately
3Mixed sourcesPartially biogenic
Biogenic CO2 from biofuels (ghg_type = 2) is reported separately in the co2e_biomass field and typically not counted toward carbon footprint totals per GHG Protocol standards.

Units per Fuel

Each fuel has specific units it can be measured in:

Natural Gas Units

  • (cubic meters) - Standard volumetric measurement
  • kWh - Energy content
  • kWh HHV - Higher heating value
  • kWh LHV - Lower heating value

Diesel/Liquid Fuel Units

  • L (liters) - Volume measurement
  • kWh - Energy content
  • kg - Mass measurement

LPG/Propane Units

  • kg - Mass measurement (most common for LPG)
  • L - Volume measurement
  • - For gaseous phase
Always check the units array for each fuel to see which units are available. Using an incompatible unit will result in an error when creating an invoice.

Best Practices

1. Cache Reference Data

Since facility fuels don’t change frequently, cache them:
# Good - Cache for 24 hours
fuels_cache = cache.get_fuels("ES")

# Bad - Fetch every time
fuels = requests.get(f"https://api.dcycle.io/api/v1/facility_fuels?country=ES")

2. Use Country Filtering

Always filter by country when you know the facility’s location:
# Good - Only fetch Spanish fuels
spanish_fuels = get_fuels(country="ES")

# Less efficient - Fetch all and filter client-side
all_fuels = get_fuels()
spanish_fuels = [f for f in all_fuels if f['country'] == 'ES']

3. Validate Unit Before Invoice Creation

Check that the unit is in the fuel’s units array:
def validate_invoice_data(fuel_id, unit_id):
    fuel = cache.get_fuel_by_id(fuel_id)
    unit_ids = [u['id'] for u in fuel['units']]

    if unit_id not in unit_ids:
        raise ValueError(f"Invalid unit for fuel '{fuel['name']}'")

    return True

4. Store Common Fuel IDs

For frequently used fuels, store their IDs in configuration:
# config.py
COMMON_FUELS_ES = {
    'natural_gas': 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
    'diesel': 'b2c3d4e5-f6g7-8901-bcde-fg2345678901',
    'propane': 'c3d4e5f6-g7h8-9012-cdef-gh3456789012'
}

# Usage - No API call needed
invoice_data = {
    "facility_fuel_id": COMMON_FUELS_ES['natural_gas'],
    # ... other fields
}