Metadata¶
Table of contents
Overview
Setup
Authentication Token
Global Metadata API
What is the Global Metadata API?
Get Types for Any Endpoint
Get Units for Any Type
Get Areas for Any Endpoint
Using POST Method
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
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.pat_token = <Your Emissions API PAT token>
api.tenant_id = <Your Emissions API Tenant Id>
[ ]:
# Install the prerequisite Python packages
%pip install pandas configparser IPython requests
[1]:
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.
[2]:
config = configparser.RawConfigParser()
config.read(['../../../auth/secrets.ini','../../../auth/config.ini'])
EAPI_PAT_TOKEN = config.get('EAPI', 'api.pat_token')
EAPI_TENANT_ID = config.get('EAPI', 'api.tenant_id')
EAPI_CLIENT_ID = 'ghgemissions-' + EAPI_TENANT_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-IBM-Envizi-Pat"] = EAPI_PAT_TOKEN
verify = True
auth_url = f"{EAPI_AUTH_ENDPOINT}"
response = requests.post(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)
Authentication Success
[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
Global Metadata API¶
The Global Metadata API provides a unified and consistent way to query metadata across all emission calculation endpoints. Instead of remembering different URLs for each endpoint, you use a single API pattern and simply specify which endpoint you’re interested in.
Why Use the Global Metadata API?¶
Simplicity: One consistent API pattern for all endpoints
Flexibility: Query any endpoint dynamically by changing a parameter
Convenience: Supports both GET (query parameters) and POST (request body) methods
Future-proof: New endpoints are automatically supported
The Three Core Endpoints¶
``GET/POST /metadata/types``: Discover all available emission source types for any endpoint
``GET/POST /metadata/units``: Find valid measurement units for specific types
``GET/POST /metadata/area``: Explore geographic coverage (countries and regions) for any endpoint
Supported Endpoints¶
You can query metadata for any of these endpoints:
``calculation`` (default) - All emission types across all scopes
``location`` - Scope 2: Purchased electricity and energy
``stationary`` - Scope 1: Stationary fuel combustion
``mobile`` - Scope 1: Mobile combustion (vehicles)
``fugitive`` - Scope 1: Fugitive emissions (refrigerants, leaks)
``transportation-and-distribution`` - Scope 3: Transportation
``economic-activity`` - Scope 3: Economic activity-based
``real-estate`` - Scope 3: Real estate
``factor`` - Emission factors database
``search`` - Search across all factors (area only)
Let’s explore each endpoint with practical examples!
Get Types for Any Endpoint¶
The /metadata/types endpoint returns all available emission source types for a specified endpoint. This helps you discover what kinds of activities or materials you can calculate emissions for.
Endpoint: GET /metadata/types?endpoint={endpoint_name}
Parameters:
endpoint(optional): The endpoint name. Defaults tocalculationif not provided.
Response: Returns a JSON object with a types array containing all available emission source types.
[11]:
# Example 1: Get all types (defaults to 'calculation' which includes everything)
types_url = f"{EAPI_ENDPOINT}/metadata/types"
response = requests.get(types_url, headers=request_headers)
if response.status_code == 200:
types_data = response.json()
types_list = types_data.get('types', [])
print(f"Total emission types available across all endpoints: {len(types_list)}")
print("\nSample types (first 20):")
for i, type_name in enumerate(types_list[:20], 1):
print(f"{i}. {type_name}")
else:
print(f"Error: {response.status_code}")
print(response.text)
Total emission types available across all endpoints: 6185
Sample types (first 20):
1. Scope 3 - Spend-based USEEIO v1.2:Recreational Goods Rental
2. Natural Gas - Scope 3:AAA
3. Perf arts, spectator sports, museums, other:Dance Companies
4. HFO-1234ze(Z)
5. Cars by Segment - Sports - Plug-in Hybrid Electric
6. HFC-263fb
7. Waste Recycled - Carpet - Scope 3
8. > 20t:B20:(E)
9. Wholesale trade:Jewelry, Watch, Precious Stone, and Precious Metal Merchant Wholesalers
10. Misc prof, scientific, technical services:Environmental Consulting Services
11. Other retail:Vending Machine Operators
12. Wood kitchen cabinets and countertops
13. Freight - Flights - Short-haul International (without RF)
14. Tobacco products
15. R504:DEFRA - Kyoto Only
16. Construction:Flooring Contractors
17. 1,1,1,2,2,3,3-Heptafluoro-3-(1,2,2,2-tetrafluoroethoxy)-propane
18. Soap and cleaning compounds
19. Petrol (100% Mineral Petrol) - Scope 3
20. Fabricated pipe and pipe fittings:With Inflation
[12]:
# Example 2: Get types for stationary endpoint
types_url = f"{EAPI_ENDPOINT}/metadata/types?endpoint=stationary"
response = requests.get(types_url, headers=request_headers)
if response.status_code == 200:
types_data = response.json()
types_list = types_data.get('types', [])
types_df = pd.DataFrame(types_list, columns=['Fuel Type'])
print(f"Total fuel types for stationary combustion: {len(types_list)}")
print("\nSample fuel types (first 15):")
display_summary(types_df.head(15))
else:
print(f"Error: {response.status_code}")
print(response.text)
Total fuel types for stationary combustion: 324
Sample fuel types (first 15):
| Fuel Type | |
|---|---|
| 0 | Other Gaseous Fossil Fuels - Acetylene |
| 1 | Methane |
| 2 | Light Fuel Oil - Commercial/Institutional |
| 3 | Natural Gas - Industrial Use |
| 4 | Liquefied Natural Gas - LNG:A |
| 5 | Biodiesel B5 |
| 6 | Gas Oil |
| 7 | Biomass Fuels - Liquid - Rendered Animal Fat |
| 8 | Coal - Tar |
| 9 | Petroleum Products - Natural Gasoline |
| 10 | Fuel Oil Stationary:AA - Other Stationary |
| 11 | Light Fuel Oil - Industrial |
| 12 | Bio Petrol |
| 13 | Petroleum Based Oils:Energy consumed - not com... |
| 14 | Other Primary Solid Biomass Fuels |
Get Units¶
The /metadata/units endpoint returns valid measurement units for a specific emission type. This is essential for ensuring your activity data uses the correct units.
Endpoint: GET /metadata/units?type={type_name}
Parameters:
type(optional): The emission source type. If not provided, returns the complete unit conversion table.
Response: Returns a JSON object with a units array containing all valid units for the specified type.
[18]:
# Example 1: Get units for Natural Gas
units_url = f"{EAPI_ENDPOINT}/metadata/units?type=Natural%20Gas"
response = requests.get(units_url, headers=request_headers)
print(response.json())
if response.status_code == 200:
units_data = response.json()
units_list = units_data.get('units', [])
units_df = pd.DataFrame(units_list)
print(f"Available units for 'Natural Gas': {len(units_list)}")
print("\nValid units:")
display_summary(units_df)
else:
print(f"Error: {response.status_code}")
print(response.text)
{'units': [{'unit': 'J', 'unitName': 'joule'}, {'unit': 'KJ', 'unitName': 'kilojoule'}, {'unit': 'MJ', 'unitName': 'megajoule'}, {'unit': 'GJ', 'unitName': 'gigajoule'}, {'unit': 'TJ', 'unitName': 'terajoule'}, {'unit': 'BTU', 'unitName': 'British thermal unit'}, {'unit': 'thm', 'unitName': 'therm'}, {'unit': 'dth', 'unitName': 'dekatherm'}, {'unit': 'kBTU', 'unitName': 'kilo British thermal unit'}, {'unit': 'MMBTU', 'unitName': 'million British thermal units'}, {'unit': 'ml', 'unitName': 'milliliter'}, {'unit': 'ml', 'unitName': 'millilitre'}, {'unit': 'l', 'unitName': 'liter'}, {'unit': 'l', 'unitName': 'litre'}, {'unit': 'kl', 'unitName': 'kiloliter'}, {'unit': 'kl', 'unitName': 'kilolitre'}, {'unit': 'm3', 'unitName': 'cubic meter'}, {'unit': 'm3', 'unitName': 'cubic metre'}, {'unit': 'cf', 'unitName': 'cubic foot'}, {'unit': 'ccf', 'unitName': 'hundred cubic feet'}, {'unit': 'Wh', 'unitName': 'watt-hour'}, {'unit': 'kWh', 'unitName': 'kilowatt-hour'}, {'unit': 'mWh', 'unitName': 'megawatt-hour'}, {'unit': 'usd', 'unitName': 'United States dollar'}, {'unit': 'st', 'unitName': 'short ton'}, {'unit': 'mcf', 'unitName': 'thousand cubic feet'}, {'unit': 'imp gal', 'unitName': 'British imperial gallon '}, {'unit': 'gal', 'unitName': 'US gallon'}, {'unit': 'bbl', 'unitName': 'barrel'}, {'unit': 'g', 'unitName': 'gram'}, {'unit': 'kg', 'unitName': 'kilogram'}, {'unit': 't', 'unitName': 'metric ton'}, {'unit': 'lb', 'unitName': 'pound'}, {'unit': 'thousand lb', 'unitName': 'thousand pounds'}, {'unit': 'million lb', 'unitName': 'million pounds'}]}
Available units for 'Natural Gas': 35
Valid units:
| unit | unitName | |
|---|---|---|
| 0 | J | joule |
| 1 | KJ | kilojoule |
| 2 | MJ | megajoule |
| 3 | GJ | gigajoule |
| 4 | TJ | terajoule |
| 5 | BTU | British thermal unit |
| 6 | thm | therm |
| 7 | dth | dekatherm |
| 8 | kBTU | kilo British thermal unit |
| 9 | MMBTU | million British thermal units |
| 10 | ml | milliliter |
| 11 | ml | millilitre |
| 12 | l | liter |
| 13 | l | litre |
| 14 | kl | kiloliter |
| 15 | kl | kilolitre |
| 16 | m3 | cubic meter |
| 17 | m3 | cubic metre |
| 18 | cf | cubic foot |
| 19 | ccf | hundred cubic feet |
| 20 | Wh | watt-hour |
| 21 | kWh | kilowatt-hour |
| 22 | mWh | megawatt-hour |
| 23 | usd | United States dollar |
| 24 | st | short ton |
| 25 | mcf | thousand cubic feet |
| 26 | imp gal | British imperial gallon |
| 27 | gal | US gallon |
| 28 | bbl | barrel |
| 29 | g | gram |
| 30 | kg | kilogram |
| 31 | t | metric ton |
| 32 | lb | pound |
| 33 | thousand lb | thousand pounds |
| 34 | million lb | million pounds |
[20]:
# Example 2: Get units for Electricity
units_url = f"{EAPI_ENDPOINT}/metadata/units?type=Electricity"
response = requests.get(units_url, headers=request_headers)
if response.status_code == 200:
units_data = response.json()
units_list = units_data.get('units', [])
units_df = pd.DataFrame(units_list)
print(f"Available units for 'Electricity': {len(units_list)}")
print("\nValid units:")
display_summary(units_df)
else:
print(f"Error: {response.status_code}")
print(response.text)
Available units for 'Electricity': 14
Valid units:
| unit | unitName | |
|---|---|---|
| 0 | J | joule |
| 1 | KJ | kilojoule |
| 2 | MJ | megajoule |
| 3 | GJ | gigajoule |
| 4 | TJ | terajoule |
| 5 | BTU | British thermal unit |
| 6 | thm | therm |
| 7 | dth | dekatherm |
| 8 | kBTU | kilo British thermal unit |
| 9 | MMBTU | million British thermal units |
| 10 | Wh | watt-hour |
| 11 | kWh | kilowatt-hour |
| 12 | mWh | megawatt-hour |
| 13 | usd | United States dollar |
Get Areas for Any Endpoint¶
The /metadata/area endpoint returns all available geographic locations (countries and regions) for a specified endpoint. This helps you understand where emission factors are available.
Endpoint: GET /metadata/area?endpoint={endpoint_name}
Parameters:
endpoint(optional): The endpoint name. Defaults tocalculationif not provided.
Response: Returns a JSON object with a locations array containing:
alpha3: ISO 3166-1 alpha-3 country codecountryName: Full country namestateProvinces: Array of state/province names (for countries with regional data)
[ ]:
# Example 1: Get areas for mobile endpoint
area_url = f"{EAPI_ENDPOINT}/metadata/area?endpoint=mobile"
response = requests.get(area_url, headers=request_headers)
if response.status_code == 200:
area_data = response.json()
locations = area_data.get('locations', [])
locations_df = pd.DataFrame(locations)
print(f"Total countries available for mobile endpoint: {len(locations)}")
print("Sample locations")
display_summary(locations_df.head(20))
else:
print(f"Error: {response.status_code}")
print(response.text)
Total countries available for mobile endpoint: 244
Sample locations
| alpha3 | countryName | stateProvinces | |
|---|---|---|---|
| 0 | ABW | Aruba | NaN |
| 1 | AFG | Afghanistan | NaN |
| 2 | AGO | Angola | NaN |
| 3 | AIA | Anguilla | NaN |
| 4 | ALA | Åland Islands | NaN |
| 5 | ALB | Albania | NaN |
| 6 | AND | Andorra | NaN |
| 7 | ARE | United Arab Emirates | [Abu Dhabi, Ajman, Dubai, Fujairah, Ras Al Kha... |
| 8 | ARG | Argentina | NaN |
| 9 | ARM | Armenia | NaN |
| 10 | ATF | French Southern Territories | NaN |
| 11 | ATG | Antigua and Barbuda | [Antigua, Barbuda] |
| 12 | AUS | Australia | [Australian Capital Territory, New South Wales... |
| 13 | AUT | Austria | [Central River, Lower River, North Bank, Upper... |
| 14 | AZE | Azerbaijan | NaN |
| 15 | BDI | Burundi | NaN |
| 16 | BEL | Belgium | NaN |
| 17 | BEN | Benin | NaN |
| 18 | BES | Bonaire | NaN |
| 19 | BFA | Burkina Faso | NaN |
Using POST Method¶
All Global Metadata API endpoints also support the POST method, which can be useful when:
You prefer sending parameters in the request body
You’re building applications that standardize on POST requests
You want to avoid URL encoding issues with special characters
The POST method accepts the same parameters as GET, but in the request body as JSON.
[22]:
# Example: POST request to get types for fugitive endpoint
types_url = f"{EAPI_ENDPOINT}/metadata/types"
request_body = {"endpoint": "fugitive"}
response = requests.post(types_url, headers=request_headers, json=request_body)
if response.status_code == 200:
types_data = response.json()
types_list = types_data.get('types', [])
types_df = pd.DataFrame(types_list, columns=['Fugitive Type'])
print(f"Total fugitive emission types: {len(types_list)}")
print("\nSample fugitive types (first 15):")
display_summary(types_df.head(15))
else:
print(f"Error: {response.status_code}")
print(response.text)
Total fugitive emission types: 682
Sample fugitive types (first 15):
| Fugitive Type | |
|---|---|
| 0 | HFE-569sf2 |
| 1 | 1,1,2-trichloro-ethene |
| 2 | R422A |
| 3 | 2-chloropropane |
| 4 | R434A |
| 5 | R-512A |
| 6 | Carbon Tetrachloride |
| 7 | R458A |
| 8 | (e)-1-chloro-2-fluoroethene |
| 9 | Perfluorobutane (PFC-3-1-10) |
| 10 | Natural Gas - NC:BBB |
| 11 | HFC-143:DEFRA - Kyoto Only |
| 12 | HFO-1234ze(Z) |
| 13 | HFC-263fb |
| 14 | R433C |