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:
Available Data Types: All activity types, fuel types, refrigerants, energy types, and transportation modes supported by each API
Units of Measurement: Valid units for each data type (kg, km, kWh, BTU, etc.)
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¶
Setup: Configure your authentication credentials (one-time setup)
Explore: Browse through the example metadata queries
Query: Run the code cells to see available types, units, and locations
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 typesGET /mobile/units?type={type}- Get units for a specific vehicle typeGET /mobile/area- Get available countries and regions
Stationary Combustion API:
GET /stationary/types- Get all fuel typesGET /stationary/units?type={type}- Get units for a specific fuel typeGET /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 typeGET /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 typesGET /transportation-and-distribution/units?type={type}- Get units for a specific transportation typeGET /transportation-and-distribution/area- Get available countries and regions
General APIs¶
Factor API:
GET /factor/types- Get all activity types with emission factorsGET /factor/units?type={type}- Get units for a specific activity typeGET /factor/area- Get available countries and regions
Usage Pattern¶
All endpoints follow the same request/response pattern shown in the examples above:
Types endpoint: Returns a list of available types/categories
Units endpoint: Returns valid units for a specific type (requires
typequery parameter)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.