Metadata

Table of contents

  • Overview

  • Setup

    • Authentication Token

  • Example Metadata Queries

    • Fugitive Emissions Metadata (Scope 1 Example)

    • Calculation Metadata (General API Example)

    • Search Metadata (Special Case)

  • Other Metadata Endpoints

  • Related Links

Overview

This notebook demonstrates how to query metadata endpoints across the IBM Envizi Emissions API. These endpoints help you discover available data types, units of measurement, and geographic locations for emissions calculations across all scopes.

What are Metadata Endpoints?

Metadata endpoints provide essential information about:

  1. Available Data Types: All activity types, fuel types, refrigerants, energy types, and transportation modes supported by each API

  2. Units of Measurement: Valid units for each data type (kg, km, kWh, BTU, etc.)

  3. Geographic Locations: Countries and state/province subdivisions available for calculations

APIs Covered in This Notebook

Scope 1 - Direct Emissions:

  • Fugitive Emissions API: Refrigerant leaks, HFCs, PFCs, natural gas leaks, and other greenhouse gas releases

  • Mobile API: Fleet vehicles, cars, vans, trucks, and other mobile sources

  • Stationary API: Boilers, furnaces, generators, and stationary fuel combustion

Scope 2 - Indirect Energy Emissions:

  • Location-Based API: Purchased electricity, steam, chilled water, and hot water

Scope 3 - Other Indirect Emissions:

  • Transportation and Distribution API: Business travel, freight transport, and logistics

General APIs:

  • Calculation API: Complete emissions calculations combining activity data with emission factors

  • Factor API: Access to emission factors for custom calculations and audit trails

  • Search API: Keyword-based search and discovery of emission factors

Why Use Metadata Endpoints?

  • Discovery: Find what data types, units, and locations are available before building your application

  • Validation: Ensure your input data uses valid types and units supported by the API

  • Planning: Understand geographic coverage and data availability for your use case

  • Integration: Build dynamic applications that adapt to available options

  • Documentation: Reference guide for building emissions calculation workflows

  • Compliance: Verify that required emission factors are available for your reporting needs

How to Use This Notebook

  1. Setup: Configure your authentication credentials (one-time setup)

  2. Explore: Browse through the example metadata queries

  3. Query: Run the code cells to see available types, units, and locations

  4. Reference: Use the results to build your emissions calculation workflows

Each metadata endpoint follows a consistent pattern:

  • Get available types/data types

  • Get units for specific types

  • Get available geographic locations

Setup

Ensure that Python 3+ is installed on your system.

Note: To run this notebook, you must first add your credentials to '../../../auth/secrets.ini' in the following format:

[EAPI]
api.api_key = <Your Emissions API Key>
api.tenant_id = <Your Emissions API Tenant Id>
api.org_id = <Your Emissions API Org Id>
[ ]:
# Install the prerequisite Python packages
%pip install pandas configparser IPython requests
[2]:
import pandas as pd
import configparser
import requests
import json
from IPython.display import display as display_summary

Authentication Token

Run the following code snippet to generate a Bearer Token by using your api_key configured in secrets.ini.

[ ]:
config = configparser.RawConfigParser()
config.read(['../../../auth/secrets.ini','../../../auth/config.ini'])

EAPI_API_KEY        = config.get('EAPI', 'api.api_key')
EAPI_TENANT_ID      = config.get('EAPI', 'api.tenant_id')
EAPI_CLIENT_ID      = 'ghgemissions-' + EAPI_TENANT_ID
EAPI_ORG_ID         = config.get('EAPI', 'api.org_id')

EAPI_AUTH_CLIENT_ID = 'saascore-' + EAPI_TENANT_ID
EAPI_AUTH_ENDPOINT  = config.get('EAPI', 'api.auth_endpoint')

EAPI_BASE_URL       = config.get('EAPI', 'api.base_url')
EAPI_ENDPOINT       = f"{EAPI_BASE_URL}"

auth_request_headers: dict = {}
auth_request_headers["X-IBM-CLIENT-ID"] = EAPI_AUTH_CLIENT_ID
auth_request_headers["X-API-KEY"] = EAPI_API_KEY

verify = True

auth_url = f"{EAPI_AUTH_ENDPOINT}?orgId={EAPI_ORG_ID}"

response = requests.get(url = auth_url,
                        headers = auth_request_headers,
                        verify  = verify
                       )

if response.status_code == 200:
    jwt_token = response.text
    print("Authentication Success")
else:
    print("Authentication Failed")
    print(response.text)
[4]:
# Create the query headers for all metadata requests
request_headers: dict = {}
request_headers["Content-Type"] = "application/json"
request_headers["x-ibm-client-id"] = EAPI_CLIENT_ID
request_headers["Authorization"] = "Bearer " + jwt_token

Example Metadata Queries

The following sections demonstrate metadata queries for three representative APIs. All other metadata endpoints follow the same pattern.

Fugitive Metadata (Scope 1)

Get Types

Endpoint: GET /fugitive/types

This endpoint returns all available fugitive data types that can be used in fugitive emission calculations. Types include:

  • HFCs (Hydrofluorocarbons): HFC-161, HFC-263fb, etc.

  • HFEs (Hydrofluoroethers): HFE-569sf2, HFE-338mcf2, HFE-236ea2 (desflurane), etc.

  • HFOs (Hydrofluoroolefins): HFO-1234ze(Z), etc.

  • PFCs (Perfluorocarbons): PFC-71-18, etc.

  • Refrigerant blends: R422A, R434A, R-512A, R421B, R-426A, R-438A, R-513A, etc.

  • Natural Gas: Various natural gas types with different scopes

  • Other chemicals: Carbon Tetrachloride, chlorinated compounds, fluorinated compounds, etc.

[5]:
# Query the types endpoint
types_url = f"{EAPI_ENDPOINT}/fugitive/types"
response = requests.get(types_url, headers=request_headers)

if response.status_code == 200:
    types_data = response.json()
    types_df = pd.DataFrame(types_data['types'], columns=['Fugitive Data Type'])
    print(f"Total data types available: {len(types_df)}\n")
    print("All available fugitive data types for emissions:")
    display_summary(types_df)
else:
    print(f"Error: {response.status_code}")
    print(response.text)
Total data types available: 575

All available fugitive data types for emissions:
Fugitive Data Type
0 HFE-569sf2
1 1,1,2-trichloro-ethene
2 R422A
3 2-chloropropane
4 R434A
... ...
570 HFE-7100
571 (e)-hex-2-en-1-ol
572 Fluoro(methoxy)methane
573 HFE-356mec3
574 HFC-245eb

575 rows × 1 columns

Get Units for a Type

Endpoint: GET /fugitive/units?type={type}

This endpoint returns the available units of measurement for a specific fugitive data type. Common units include:

  • Mass units: g (grams), kg (kilograms), t (tonnes), lb (pounds), st (short tons)

  • Large mass units: thousand lb, million lb

Fugitive emissions are typically calculated based on the mass of refrigerant leaked or released.

Example: Query units for “R134a:NGERs - Method 1”

[6]:
# Example: Get units for "R134a:NGERs - Method 1"
data_type = "R134a:NGERs - Method 1"
units_url = f"{EAPI_ENDPOINT}/fugitive/units?type={data_type}"

response = requests.get(units_url, headers=request_headers)

if response.status_code == 200:
    units_data = response.json()
    units_df = pd.DataFrame(units_data['units'], columns=['Unit'])
    print(f"Available units for '{data_type}':\n")
    display_summary(units_df)
else:
    print(f"Error: {response.status_code}")
    print(response.text)
Available units for 'R134a:NGERs - Method 1':

Unit
0 g
1 kg
2 t
3 lb
4 thousand lb
5 million lb
6 st

Get Available Locations

Endpoint: GET /fugitive/area

This endpoint returns all available countries and their state/province subdivisions (where applicable) that can be used in emission calculations. The response includes:

  • alpha3: ISO 3166-1 alpha-3 country code

  • countryName: Full country name

  • stateProvinces: Array of state/province names (for countries with regional data)

[7]:
# Query the area endpoint
area_url = f"{EAPI_ENDPOINT}/fugitive/area"
response = requests.get(area_url, headers=request_headers)

if response.status_code == 200:
    area_data = response.json()

    # Create a list to hold location data
    location_list = []
    countries_with_states = []

    for location in area_data['locations']:
        alpha3 = location.get('alpha3', '')
        country_name = location.get('countryName', '')
        state_provinces = location.get('stateProvinces', [])

        if state_provinces:
            countries_with_states.append(country_name)
            # If there are state/provinces, create a row for each
            for state in state_provinces:
                location_list.append({
                    'Country Code (alpha3)': alpha3,
                    'Country Name': country_name,
                    'State/Province': state
                })
        else:
            # If no state/provinces, just add the country
            location_list.append({
                'Country Code (alpha3)': alpha3,
                'Country Name': country_name,
                'State/Province': 'N/A'
            })

    locations_df = pd.DataFrame(location_list)

    print(f"Total countries available: {len(area_data['locations'])}")
    print(f"Countries with state/province subdivisions: {len(countries_with_states)}\n")
    print("Sample locations (first 20 rows):")
    display_summary(locations_df.head(20))
else:
    print(f"Error: {response.status_code}")
    print(response.text)
Total countries available: 244
Countries with state/province subdivisions: 10

Sample locations (first 20 rows):
Country Code (alpha3) Country Name State/Province
0 ABW Aruba N/A
1 AFG Afghanistan N/A
2 AGO Angola N/A
3 AIA Anguilla N/A
4 ALA Åland Islands N/A
5 ALB Albania N/A
6 AND Andorra N/A
7 ARE United Arab Emirates Abu Dhabi
8 ARE United Arab Emirates Ajman
9 ARE United Arab Emirates Dubai
10 ARE United Arab Emirates Fujairah
11 ARE United Arab Emirates Ras Al Khaimah
12 ARE United Arab Emirates Sharjah
13 ARE United Arab Emirates Umm Al Quwain
14 ARG Argentina N/A
15 ARM Armenia N/A
16 ATF French Southern Territories N/A
17 ATG Antigua and Barbuda Antigua
18 ATG Antigua and Barbuda Barbuda
19 AUS Australia Australian Capital Territory

Calculation Metadata (General API Example)

Get Types

Endpoint: GET /carbon/calculation/types

This endpoint returns all available calculation types. These types represent different categories of emissions calculations such as:

  • Transportation types (vehicles, flights, etc.)

  • Energy sources (natural gas, electricity, etc.)

  • Materials and products

  • Waste management

  • Industry-specific categories

[8]:
# Query the types endpoint
types_url = f"{EAPI_ENDPOINT}/calculation/types"
response = requests.get(types_url, headers=request_headers)

if response.status_code == 200:
    types_data = response.json()
    types_df = pd.DataFrame(types_data['types'], columns=['Calculation Type'])
    print(f"Total calculation types available: {len(types_df)}\n")
    print("All available calculation types:")
    display_summary(types_df)
else:
    print(f"Error: {response.status_code}")
    print(response.text)
Total calculation types available: 5687

All available calculation types:
Calculation Type
0 Timber and raw forest products
1 Scope 3 - Spend-based USEEIO v1.2:Recreational...
2 Other transportation and support activities:Al...
3 Scope 3 - Spend-based USEEIO v1.2:Plastics Pac...
4 Natural Gas - Scope 3:AAA
... ...
5682 Material Use - Paper and Board - Board
5683 Stainless Steel Sheet Products
5684 Company Vehicles:Engine size 1.4-2.0 litres - ...
5685 Fluoro(methoxy)methane
5686 HFE-356mec3

5687 rows × 1 columns

Get Units for a Type

Endpoint: GET /carbon/calculation/units?type={type}

This endpoint returns the available units of measurement for a specific calculation type. Units vary by activity type:

  • Spend-based activities: Typically use currency units (USD)

  • Material activities: May use mass, volume, or currency units

  • Transportation: Distance units (m, km, mi, etc.)

  • Waste: Mass units (kg, t, lb, etc.)

  • Refrigerants: Mass units (g, kg, t, lb, etc.)

Example: Query units for “Tobacco products”

[9]:
# Example: Get units for "Tobacco products"
calculation_type = "Tobacco products"
units_url = f"{EAPI_ENDPOINT}/calculation/units?type={calculation_type}"

response = requests.get(units_url, headers=request_headers)

if response.status_code == 200:
    units_data = response.json()
    units_df = pd.DataFrame(units_data['units'], columns=['Unit'])
    print(f"Available units for '{calculation_type}':\n")
    display_summary(units_df)
else:
    print(f"Error: {response.status_code}")
    print(response.text)
Available units for 'Tobacco products':

Unit
0 usd

Get Available Locations

Endpoint: GET /carbon/calculation/area

This endpoint returns all available countries and their state/province subdivisions (where applicable) for which calculations are available. The response includes:

  • alpha3: ISO 3166-1 alpha-3 country code

  • countryName: Full country name

  • stateProvinces: Array of state/province names (for countries with regional factors)

Location data is crucial as emission factors can vary significantly by region due to:

  • Different energy grid compositions

  • Regional regulations and methodologies

  • Local fuel compositions

  • Climate and environmental conditions

[10]:
# Query the area endpoint
area_url = f"{EAPI_ENDPOINT}/calculation/area"
response = requests.get(area_url, headers=request_headers)

if response.status_code == 200:
    area_data = response.json()

    # Create a list to hold location data
    location_list = []
    countries_with_states = []

    for location in area_data['locations']:
        alpha3 = location.get('alpha3', '')
        country_name = location.get('countryName', '')
        state_provinces = location.get('stateProvinces', [])

        if state_provinces:
            countries_with_states.append(country_name)
            # If there are state/provinces, create a row for each
            for state in state_provinces:
                location_list.append({
                    'Country Code (alpha3)': alpha3,
                    'Country Name': country_name,
                    'State/Province': state
                })
        else:
            # If no state/provinces, just add the country
            location_list.append({
                'Country Code (alpha3)': alpha3,
                'Country Name': country_name,
                'State/Province': 'N/A'
            })

    locations_df = pd.DataFrame(location_list)

    print(f"Total countries available: {len(area_data['locations'])}")
    print(f"Countries with state/province subdivisions: {len(countries_with_states)}\n")
    print("Sample locations (first 20 rows):")
    display_summary(locations_df.head(20))
else:
    print(f"Error: {response.status_code}")
    print(response.text)
Total countries available: 244
Countries with state/province subdivisions: 10

Sample locations (first 20 rows):
Country Code (alpha3) Country Name State/Province
0 ABW Aruba N/A
1 AFG Afghanistan N/A
2 AGO Angola N/A
3 AIA Anguilla N/A
4 ALA Åland Islands N/A
5 ALB Albania N/A
6 AND Andorra N/A
7 ARE United Arab Emirates Abu Dhabi
8 ARE United Arab Emirates Ajman
9 ARE United Arab Emirates Dubai
10 ARE United Arab Emirates Fujairah
11 ARE United Arab Emirates Ras Al Khaimah
12 ARE United Arab Emirates Sharjah
13 ARE United Arab Emirates Umm Al Quwain
14 ARG Argentina N/A
15 ARM Armenia N/A
16 ATF French Southern Territories N/A
17 ATG Antigua and Barbuda Antigua
18 ATG Antigua and Barbuda Barbuda
19 AUS Australia Australian Capital Territory

Search Metadata (Special Case)

Get Available Locations

Endpoint: GET /factor/search/area

This endpoint returns all available countries and their state/province subdivisions (where applicable) for which emission factors can be searched. The response includes:

  • alpha3: ISO 3166-1 alpha-3 country code

  • countryName: Full country name

  • stateProvinces: Array of state/province names (for countries with regional factors)

Understanding location availability is crucial because:

  • Emission factors vary significantly by region

  • Some countries have state/province-level granularity

  • Regional factors reflect local energy grids, fuel compositions, and regulations

  • You can plan your searches based on available geographic coverage

Note: The Search API only has an area endpoint. It does not have types or units endpoints since it searches across all factor types.

[11]:
# Query the area endpoint
area_url = f"{EAPI_ENDPOINT}/factor/search/area"
response = requests.get(area_url, headers=request_headers)

if response.status_code == 200:
    area_data = response.json()

    # Create a list to hold location data
    location_list = []
    countries_with_states = []

    for location in area_data['locations']:
        alpha3 = location.get('alpha3', '')
        country_name = location.get('countryName', '')
        state_provinces = location.get('stateProvinces', [])

        if state_provinces:
            countries_with_states.append(country_name)
            # If there are state/provinces, create a row for each
            for state in state_provinces:
                location_list.append({
                    'Country Code (alpha3)': alpha3,
                    'Country Name': country_name,
                    'State/Province': state
                })
        else:
            # If no state/provinces, just add the country
            location_list.append({
                'Country Code (alpha3)': alpha3,
                'Country Name': country_name,
                'State/Province': 'N/A'
            })

    locations_df = pd.DataFrame(location_list)

    print(f"Total countries available for factor search: {len(area_data['locations'])}")
    print(f"Countries with state/province subdivisions: {len(countries_with_states)}\n")
    print("Sample locations (first 20 rows):")
    display_summary(locations_df.head(20))
else:
    print(f"Error: {response.status_code}")
    print(response.text)
Total countries available for factor search: 244
Countries with state/province subdivisions: 10

Sample locations (first 20 rows):
Country Code (alpha3) Country Name State/Province
0 ABW Aruba N/A
1 AFG Afghanistan N/A
2 AGO Angola N/A
3 AIA Anguilla N/A
4 ALA Åland Islands N/A
5 ALB Albania N/A
6 AND Andorra N/A
7 ARE United Arab Emirates Abu Dhabi
8 ARE United Arab Emirates Ajman
9 ARE United Arab Emirates Dubai
10 ARE United Arab Emirates Fujairah
11 ARE United Arab Emirates Ras Al Khaimah
12 ARE United Arab Emirates Sharjah
13 ARE United Arab Emirates Umm Al Quwain
14 ARG Argentina N/A
15 ARM Armenia N/A
16 ATF French Southern Territories N/A
17 ATG Antigua and Barbuda Antigua
18 ATG Antigua and Barbuda Barbuda
19 AUS Australia Australian Capital Territory

Other Metadata Endpoints

The following APIs work the same way as the examples above. Simply replace the endpoint name in the URL:

Scope 1 APIs (Direct Emissions)

Mobile Combustion API:

  • GET /mobile/types - Get all mobile vehicle types

  • GET /mobile/units?type={type} - Get units for a specific vehicle type

  • GET /mobile/area - Get available countries and regions

Stationary Combustion API:

  • GET /stationary/types - Get all fuel types

  • GET /stationary/units?type={type} - Get units for a specific fuel type

  • GET /stationary/area - Get available countries and regions

Scope 2 APIs (Indirect Energy Emissions)

Location-Based Emissions API:

  • GET /location/types - Get all energy types (electricity, steam, etc.)

  • GET /location/units?type={type} - Get units for a specific energy type

  • GET /location/area - Get available countries and regions

Scope 3 APIs (Other Indirect Emissions)

Transportation and Distribution API:

  • GET /transportation-and-distribution/types - Get all transportation types

  • GET /transportation-and-distribution/units?type={type} - Get units for a specific transportation type

  • GET /transportation-and-distribution/area - Get available countries and regions

General APIs

Factor API:

  • GET /factor/types - Get all activity types with emission factors

  • GET /factor/units?type={type} - Get units for a specific activity type

  • GET /factor/area - Get available countries and regions

Usage Pattern

All endpoints follow the same request/response pattern shown in the examples above:

  1. Types endpoint: Returns a list of available types/categories

  2. Units endpoint: Returns valid units for a specific type (requires type query parameter)

  3. Area endpoint: Returns available countries and state/province subdivisions

Simply copy the code from the examples above and replace:

  • The endpoint path (e.g., /fugitive//mobile/)

  • The column names in DataFrames for clarity

  • The example type values when querying units

All responses use the same JSON structure, so the parsing code remains identical.