The Team Metadata API is an extension-callable Cloud Function that provides comprehensive access to all teams and their associated metadata, including custom fields, stage configurations, and data models. This API is designed for external integrations, automation tools, and administrative workflows.
Retrieves all teams from the database along with their complete metadata structure, including:
Team configuration (name, category, groups, webhooks)
Deal stage definitions (s0-s4) with labels and associated activities
Custom field schemas for all entity types (account, contact, deal, activity)
Sub-collection definitions
Required: Admin authentication
Only users with admin: true in their user document can call this function. The function verifies authentication and admin status before returning data.
Method: Callable Cloud Function
Parameters: None
Example (JavaScript/TypeScript):
import { getFunctions, httpsCallable } from 'firebase/functions';const functions = getFunctions();const getAllTeamsMetadata = httpsCallable(functions, 'getAllTeamsMetadata');try {const result = await getAllTeamsMetadata();const data = result.data;console.log(`Retrieved ${data.count} teams`);console.log(data.teams);} catch (error) {console.error('Error:', error.message);}
Example (Flutter/Dart):
import 'package:cloud_functions/cloud_functions.dart';final functions = FirebaseFunctions.instance;final callable = functions.httpsCallable('getAllTeamsMetadata');try {final result = await callable.call();final data = result.data as Map<String, dynamic>;final count = data['count'] as int;final teams = data['teams'] as List;print('Retrieved $count teams');} catch (e) {print('Error: $e');}
{"success": true,"count": 2,"teams": [{"id": "teamId123","name": "Sales Team","category": "sales","nextTeam": "teamId456","bigQuerySyncEnabled": true,"mcp": true,"groups": {"sales-group": "G1","managers": "O1"},"webhooks": {"s0": {"url": "https://example.com/webhook","token": "bearer-token"}},"stages": {"s0": {"label": "Initial Contact","activities": ["Schedule discovery call","Qualify opportunity"],"webhook": {"url": "https://example.com/webhook","token": "bearer-token"}},"s1": {"label": "Qualification","activities": ["Review requirements","Prepare proposal"],"webhook": null},"s2": {"label": "Proposal","activities": [],"webhook": null},"s3": {"label": "Negotiation","activities": [],"webhook": null},"s4": {"label": "Closed","activities": [],"webhook": null}},"customFields": {"account": {"industry": {"type": "string","label": "Industry","required": false},"annualRevenue": {"type": "number","label": "Annual Revenue","required": false}},"contact": {"jobTitle": {"type": "string","label": "Job Title","required": false}},"deal": {"contractType": {"type": "string","label": "Contract Type","required": false,"options": ["Annual", "Monthly", "One-time"]}},"activity": {"priority": {"type": "string","label": "Priority","required": false,"options": ["Low", "Medium", "High"]}}},"subCollections": {"documents": {"name": "Documents","fields": {"title": { "type": "string", "required": true },"url": { "type": "string", "required": true }}}}}]}
success (boolean): Always true on successful response
count (number): Total number of teams returned
teams (array): Array of team objects
id (string): Team document ID
name (string): Team name
category (string): Team category ("pre_sales", "sales", or "after_sales")
nextTeam (string|null): ID of the next team in workflow (for s3 stage transitions)
bigQuerySyncEnabled (boolean): Whether BigQuery sync is enabled for this team
mcp (boolean): Whether the team has an MCP API key configured
groups (object): Map of group names to sharing policy codes ("R1", "G1", "O1")
webhooks (object): Webhook configurations per stage, each with url and token keys
stages (object): Stage definitions for s0-s4
customFields (object): Custom field schemas per entity type
subCollections (object): Sub-collection definitions (if present)
label (string): Display label for the stage
activities (array): List of generic activities associated with this stage
webhook (object|null): Webhook configuration for this stage, or null if not configured
Custom fields are organized by entity type (account, contact, deal, activity). Each field definition includes:
type (string): Field type ("string", "number", "boolean", "date", etc.)
label (string): Display label
required (boolean): Whether the field is required
options (array, optional): Available options for select/enum fields
The function may throw the following errors:
"User must be authenticated": The caller is not authenticated
"User must be an admin to access team metadata": The caller is authenticated but not an admin
"Failed to fetch teams metadata: [error message]": An error occurred during data retrieval
External Integrations: Third-party systems can fetch team configurations to understand data models and workflows
Automation Tools: MCP servers and automation agents can use this to understand team-specific custom fields and stage activities
Data Migration: Export team metadata for backup or migration purposes
Administrative Dashboards: Build custom admin interfaces that display team configurations
Workflow Automation: Understand stage activities and webhook configurations for automated workflows
Performance: The function loads data from both Firestore (teams collection) and Firebase Storage (labels.json and datamodel.json files). For teams with large metadata files, response times may vary.
Data Freshness: The function fetches data in real-time. Changes to team metadata are immediately reflected in subsequent calls.
Storage Structure: Labels are stored in {teamId}/labels.json and custom fields in {teamId}/datamodel.json in Firebase Storage.
Stage Activities: Activities are stored as comma-separated strings in labels (e.g., s0_activities) and parsed into arrays in the response.
const result = await getAllTeamsMetadata();const teams = result.data.teams;// Find a specific teamconst salesTeam = teams.find(t => t.name === "Sales Team");// Access stage informationconsole.log(salesTeam.stages.s0.label); // "Initial Contact"console.log(salesTeam.stages.s0.activities); // ["Schedule discovery call", "Qualify opportunity"]// Access custom fieldsconst dealCustomFields = salesTeam.customFields.deal;Object.keys(dealCustomFields).forEach(fieldKey => {const field = dealCustomFields[fieldKey];console.log(`${field.label} (${field.type})`);});// Check webhook configurationif (salesTeam.stages.s0.webhook) {console.log(`Webhook URL: ${salesTeam.stages.s0.webhook.url}`);}