Google Sheets
To use the Scope3 API in Google Sheets, you can create a custom function that calls the API and returns the carbon footprint of AI inferences. This function can be used in any cell in your Google Sheet to calculate the carbon footprint of AI models.
Step 1: Create a custom function
Copy the following code and paste it into the script editor in your Google Sheet. To open the script editor, go to Extensions
> Apps Script
and paste the code into the editor.
function mapInputs(data) {
// Get headers (first row)
const headers = data[0].map(header => header.toString().toLowerCase().trim());
// Remove header row from data
const rows = data.slice(1);
// Initialize the request object
const impactRequest = {
rows: []
};
// Map known column names to API fields
const columnMappings = {
'model_family': 'family',
'model_name': 'name',
'cloud_id': 'cloud_id',
'cloud_instance_id': 'cloud_instance_id',
'request_time': 'requestTime',
'cloud_region': 'cloud_region',
'country': 'country',
'region': 'region',
'task': 'task',
'input_tokens': 'input_tokens',
'output_tokens': 'output_tokens',
'input_images': 'input_images',
'output_images': 'output_images'
};
// Process each row
rows.forEach(row => {
// Skip empty rows
if (!row || row.every(cell => cell === '' || cell === null || cell === undefined)) {
return;
}
// Create an object to store the transformed row data
const rowData = {
model: {},
node: {}
};
// Map each column value to the appropriate field
headers.forEach((header, index) => {
const value = row[index];
// Skip empty values
if (value === '' || value === null || value === undefined) {
return;
}
// Handle special cases for nested objects
if (header.startsWith('model_')) {
// Remove 'model_' prefix and map to model object
const modelField = columnMappings[header] || header.replace('model_', '');
rowData.model[modelField] = value;
} else if (header.startsWith('node_')) {
// Remove 'node_' prefix and map to node object
const nodeField = header.replace('node_', '');
rowData.node[nodeField] = value;
} else if (header in columnMappings) {
// Map other known fields directly
rowData[columnMappings[header]] = value;
}
// Handle numeric fields
if (header === 'input_tokens' || header === 'output_tokens') {
rowData[columnMappings[header]] = parseInt(value, 10);
}
// Handle arrays
if (header === 'input_images' || header === 'output_images') {
rowData[columnMappings[header]] = value.split(",");
}
});
// Clean up empty objects
if (Object.keys(rowData.model).length === 0) {
delete rowData.model;
}
if (Object.keys(rowData.node).length === 0) {
delete rowData.node;
}
// Add the processed row to the request
if (Object.keys(rowData).length > 0) {
impactRequest.rows.push(rowData);
}
});
return impactRequest;
}
/**
* Model the carbon footprint of AI inferences using the Scope3 API.
* Example usage in Google Sheets:
* =getAICarbonFootprint(
* "your-bearer-token",
* A2:C10 // Range containing headers and rows
* )
*
* @param {string} accessToken - The Bearer token for authentication
* @param {array} inputs - Array of arrays containing header rows that map to the inputs
* @return {array} Array of arrays containing [usage_energy_wh, usage_emissions_gco2e , usage_water_ml, embodied_emissions_gco2e, embodied_water_ml] for each input
* @customfunction
*/
function getAICarbonFootprint(accessToken, inputs) {
const url = 'https://aiapi.scope3.com/impact';
// Validate inputs
if (!inputs) {
throw new Error('All parameters are required');
}
requestData = mapInputs(inputs)
Logger.log(JSON.stringify(requestData));
const options = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(requestData),
'headers': {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
'muteHttpExceptions': true
};
try {
const response = UrlFetchApp.fetch(url, options);
const responseCode = response.getResponseCode();
if (responseCode !== 200) {
const errorText = response.getContentText();
throw new Error(`API request failed with status ${responseCode}: ${errorText}`);
}
Logger.log(response.getContentText());
const json = JSON.parse(response.getContentText());
// Return array of results
return json.rows.map(row => [
row.total_impact.usage_energy_wh || 0,
row.total_impact.usage_emissions_gco2e || 0,
row.total_impact.usage_water_ml || 0,
row.total_impact.embodied_emissions_gco2e || 0,
row.total_impact.embodied_water_ml || 0,
]);
} catch (error) {
throw new Error(`API request failed: ${error.message}`);
}
}
/**
* List all models supported by the Scope3 API
* Example usage in Google Sheets:
* =listModels(
* "your-bearer-token",
* "claude" // optional family
* )
*
* @param {string} accessToken - The Bearer token for authentication
* @param {string} family - Family to filter by
* @return {array} Array of arrays containing [model_id, family, model_name] for each input
* @customfunction
*/
function listModels(accessToken, family) {
const url = 'https://aiapi.scope3.com/model';
if (family) {
url += "?family=" + encodeURI(family)
}
const options = {
'method': 'get',
'headers': {
'Authorization': `Bearer ${accessToken}`,
},
'muteHttpExceptions': true
};
try {
const response = UrlFetchApp.fetch(url, options);
const responseCode = response.getResponseCode();
if (responseCode !== 200) {
const errorText = response.getContentText();
throw new Error(`API request failed with status ${responseCode}: ${errorText}`);
}
Logger.log(response.getContentText());
const json = JSON.parse(response.getContentText());
// Return array of results
return json.models.map(row => [
row.id, row.family, row.name
]);
} catch (error) {
throw new Error(`API request failed: ${error.message}`);
}
}
/**
* List all nodes supported by the Scope3 API
* Example usage in Google Sheets:
* =listNodes(
* "your-bearer-token",
* "aws" // optional cloud
* )
*
* @param {string} accessToken - The Bearer token for authentication
* @param {string} cloud - Cloud to filter by
* @return {array} Array of arrays containing [node_id, cloud_id, cloud_instance_id, gpu_id, gpu_count] for each input
* @customfunction
*/
function listNodes(accessToken, cloud) {
const url = 'https://aiapi.scope3.com/node';
if (cloud) {
url += "?cloud=" + encodeURI(cloud)
}
const options = {
'method': 'get',
'headers': {
'Authorization': `Bearer ${accessToken}`,
},
'muteHttpExceptions': true
};
try {
const response = UrlFetchApp.fetch(url, options);
const responseCode = response.getResponseCode();
if (responseCode !== 200) {
const errorText = response.getContentText();
throw new Error(`API request failed with status ${responseCode}: ${errorText}`);
}
Logger.log(response.getContentText());
const json = JSON.parse(response.getContentText());
// Return array of results
return json.nodes.map(row => [
row.id, row.cloud_id, row.cloud_instance_id, row.gpu_id, row.gpu_count
]);
} catch (error) {
throw new Error(`API request failed: ${error.message}`);
}
}
Step 2: Use the custom function
After you’ve added the custom function to your Google Sheet, you can use it in any cell to calculate the carbon footprint of AI inferences. Set up your Google Sheet with the following columns:
family
: The model family (e.g., ‘claude’)model
: The model name (e.g., ‘3.5 Sonnet’)input_tokens
: The number of input tokensoutput_tokens
: The number of output tokens
Then, put the custom function in the adjacent cell to calculate the carbon footprint of AI inferences. For example, if your inputs are in cells A2:C10
, you can use the following formula:
=getAICarbonFootprint(
"your-bearer-token",
"US",
"h100",
A2:D10 // Range containing family, model, input_tokens, and output_tokens
)
The sheet should look like this, with the custom function in cell E3.