Export All Architect Flows as JSON Using the Genesys Cloud CX as Code CLI

Export All Architect Flows as JSON Using the Genesys Cloud CX as Code CLI

What You Will Build

  • One sentence: A Python script that authenticates with Genesys Cloud and leverages the genesys-cloud-cx-as-code CLI to export every Architect flow in your organization into a structured JSON directory.
  • One sentence: This uses the Genesys Cloud Platform API for authentication and the official genesys-cloud-cx-as-code CLI for the heavy lifting of flow serialization.
  • One sentence: The tutorial covers Python 3.9+ for orchestration and Bash for CLI execution.

Prerequisites

  • OAuth Client Type: Confidential Client (Client Credentials Grant). You must have a Genesys Cloud OAuth client with the admin scope or specific architect:flow:read scopes.
  • SDK/CLI Version: genesys-cloud-cx-as-code CLI v0.25.0 or later.
  • Language/Runtime: Python 3.9+ and Node.js 16+ (required by the CLI).
  • External Dependencies:
    • genesys-cloud-cx-as-code (installed via npm install -g @genesys/cloud-cx-as-code-cli or npx).
    • httpx for Python (optional, if you prefer a pure Python approach, but this tutorial focuses on the CLI as requested).
    • os and subprocess (standard library).

Authentication Setup

The CX as Code CLI relies on the Genesys Cloud SDK for JavaScript under the hood. It supports two primary authentication modes:

  1. Environment Variables: Setting GENESYS_CLOUD_REGION, GENESYS_CLOUD_CLIENT_ID, and GENESYS_CLOUD_CLIENT_SECRET.
  2. Config File: Using genesys-cloud-cx-as-code config init to create a .genesys config file.

For programmatic automation, we will inject the credentials via environment variables to avoid exposing secrets in plaintext scripts.

Required Scopes:

  • architect:flow:read (Minimum)
  • admin (Recommended for full visibility including private flows)

Implementation

Step 1: Install and Configure the CLI

Before writing Python code, ensure the CLI is available. The CLI is a Node.js application.

# Install the CLI globally
npm install -g @genesys/cloud-cx-as-code-cli

# Verify installation
genesys-cloud-cx-as-code --version

Step 2: Create the Python Orchestration Script

We will write a Python script that:

  1. Sets up the necessary environment variables for the CLI.
  2. Executes the genesys-cloud-cx-as-code export command.
  3. Handles the output directory structure.

The genesys-cloud-cx-as-code export command is the core mechanism. By default, it exports all entities. To target only Architect flows, we use the --types flag.

import os
import sys
import subprocess
import shutil
from pathlib import Path
from typing import Optional

class GenesysFlowExporter:
    def __init__(self, region: str, client_id: str, client_secret: str, output_dir: str = "./exports"):
        self.region = region
        self.client_id = client_id
        self.client_secret = client_secret
        self.output_dir = Path(output_dir)
        
    def _setup_env(self) -> dict:
        """
        Creates a modified environment dictionary with OAuth credentials.
        This prevents polluting the parent process environment.
        """
        env = os.environ.copy()
        env["GENESYS_CLOUD_REGION"] = self.region
        env["GENESYS_CLOUD_CLIENT_ID"] = self.client_id
        env["GENESYS_CLOUD_CLIENT_SECRET"] = self.client_secret
        return env

    def _clean_output_dir(self) -> None:
        """
        Removes existing export data to prevent merge conflicts 
        or stale data issues.
        """
        if self.output_dir.exists():
            shutil.rmtree(self.output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)
        print(f"Created clean output directory: {self.output_dir}")

    def export_flows(self, include_private: bool = True) -> bool:
        """
        Executes the CX as Code CLI to export Architect flows.
        
        Args:
            include_private: If True, exports private flows as well. 
                            Requires admin scope.
        
        Returns:
            True if successful, False otherwise.
        """
        # Construct the CLI command
        # --types: Specifies we only want 'flows'
        # --output-dir: Where to save the JSON files
        # --include-private: Include private flows (if scope allows)
        cmd = [
            "genesys-cloud-cx-as-code",
            "export",
            "--types", "flows",
            "--output-dir", str(self.output_dir),
        ]
        
        if include_private:
            cmd.append("--include-private")

        # Setup environment with credentials
        env_vars = self._setup_env()
        
        # Clean the directory before export
        self._clean_output_dir()

        print("Starting Genesys Cloud Architect Flow Export...")
        print(f"Command: {' '.join(cmd)}")
        print("-" * 40)

        try:
            # Execute the CLI command
            # capture_output=True ensures we can read stdout/stderr
            # env=env_vars passes our OAuth credentials
            result = subprocess.run(
                cmd,
                env=env_vars,
                capture_output=True,
                text=True,
                check=False # We handle returncode manually
            )

            if result.returncode != 0:
                print("ERROR: CLI execution failed.")
                print(f"STDOUT: {result.stdout}")
                print(f"STDERR: {result.stderr}")
                return False

            print("SUCCESS: Export completed.")
            print(f"STDOUT: {result.stdout}")
            
            # Validate that files were created
            flow_files = list(self.output_dir.glob("**/flow.json"))
            if not flow_files:
                print("WARNING: No flow.json files found in output directory.")
                return False
            
            print(f"Exported {len(flow_files)} flow definitions.")
            return True

        except FileNotFoundError:
            print("ERROR: 'genesys-cloud-cx-as-code' command not found. Is it installed globally?")
            return False
        except Exception as e:
            print(f"UNEXPECTED ERROR: {e}")
            return False

if __name__ == "__main__":
    # In production, load these from a secure vault or .env file
    REGION = "mypurecloud.com"  # Example: us-east-1.mygenesys.com
    CLIENT_ID = "your_client_id_here"
    CLIENT_SECRET = "your_client_secret_here"

    if CLIENT_ID == "your_client_id_here":
        print("Please configure your CLIENT_ID and CLIENT_SECRET in the script.")
        sys.exit(1)

    exporter = GenesysFlowExporter(
        region=REGION,
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,
        output_dir="./architect_exports"
    )

    success = exporter.export_flows(include_private=True)
    sys.exit(0 if success else 1)

Step 3: Understanding the Output Structure

The CX as Code CLI does not output a single flat JSON file. It creates a directory structure that mirrors the Genesys Cloud entity hierarchy. This is crucial for version control (Git) and diffing.

For each flow, the CLI creates a directory named after the Flow ID. Inside, you will find:

  1. flow.json: The main definition of the flow.
  2. flow-refs.json: References to other entities (like IVRs or WebChat).
  3. flow-entities/: A folder containing dependent entities (like Prompt, Queue, or User objects) if they were exported alongside the flow.

Example Directory Structure:

./architect_exports/
└── flows/
    └── <flow-id>/
        ├── flow.json
        ├── flow-refs.json
        └── flow-entities/
            ├── prompts/
            │   └── <prompt-id>.json
            └── queues/
                └── <queue-id>.json

Step 4: Parsing the Exported JSON (Optional Validation)

If you need to programmatically verify the exports or extract specific metadata (e.g., “Which flows contain a ‘Transfer’ step?”), you can parse the generated JSON.

import json
from pathlib import Path

def analyze_flows(export_dir: Path) -> list[dict]:
    """
    Reads all exported flow.json files and extracts basic metadata.
    """
    flows_data = []
    flows_dir = export_dir / "flows"
    
    if not flows_dir.exists():
        print(f"Flows directory not found at {flows_dir}")
        return flows_data

    for flow_folder in flows_dir.iterdir():
        flow_json_path = flow_folder / "flow.json"
        
        if flow_json_path.exists():
            try:
                with open(flow_json_path, 'r', encoding='utf-8') as f:
                    flow_data = json.load(f)
                    
                    # Extract key metadata
                    metadata = {
                        "id": flow_data.get("id"),
                        "name": flow_data.get("name"),
                        "version": flow_data.get("version"),
                        "status": flow_data.get("status"),
                        "type": flow_data.get("type"), # e.g., 'voice', 'digital'
                        "has_draft": flow_data.get("draft", {}).get("id") is not None
                    }
                    flows_data.append(metadata)
            except json.JSONDecodeError as e:
                print(f"Error parsing {flow_json_path}: {e}")
            except Exception as e:
                print(f"Unexpected error reading {flow_json_path}: {e}")
                
    return flows_data

# Usage
if __name__ == "__main__" and "analyze" in sys.argv:
    export_path = Path("./architect_exports")
    flows = analyze_flows(export_path)
    for flow in flows:
        print(f"Flow: {flow['name']} (ID: {flow['id']}) - Status: {flow['status']}")

Complete Working Example

Combine the classes above into a single file export_flows.py.

  1. Install Node.js and the CLI.
  2. Install Python dependencies (none required beyond standard library for the basic script, but httpx is recommended for future API calls).
  3. Run the script.
# 1. Install CLI
npm install -g @genesys/cloud-cx-as-code-cli

# 2. Create the Python script (save as export_flows.py)
# [Insert the GenesysFlowExporter class code from Step 2 here]

# 3. Run the script
python export_flows.py

Expected Console Output:

Created clean output directory: ./architect_exports
Starting Genesys Cloud Architect Flow Export...
Command: genesys-cloud-cx-as-code export --types flows --output-dir ./architect_exports --include-private
----------------------------------------
SUCCESS: Export completed.
STDOUT: Exported 15 flows.
Exported 15 flow definitions.

Common Errors & Debugging

Error: 401 Unauthorized / “Invalid Client Credentials”

Cause: The GENESYS_CLOUD_CLIENT_ID or GENESYS_CLOUD_CLIENT_SECRET environment variables are incorrect, or the OAuth client is disabled.

Fix:

  1. Verify the Client ID and Secret in the Genesys Cloud Admin Console (Admin > Security > OAuth).
  2. Ensure the OAuth client has the admin or architect:flow:read scope.
  3. Check that the GENESYS_CLOUD_REGION matches your organization’s region (e.g., mypurecloud.com for US, de1.mypurecloud.com for Germany).

Code Check:
Ensure the _setup_env method in the Python script is correctly passing the variables to the subprocess.

Error: 403 Forbidden / “Insufficient Permissions”

Cause: The OAuth client does not have permission to read private flows, or the user associated with the client (if using JWT) lacks Admin rights.

Fix:

  1. If exporting private flows (--include-private), the OAuth client must have the admin scope.
  2. If you only want public flows, remove the --include-private flag from the command list in Step 2.

Error: “genesys-cloud-cx-as-code: command not found”

Cause: The CLI is not installed globally or is not in the system PATH.

Fix:

  1. Run npm install -g @genesys/cloud-cx-as-code-cli.
  2. Verify installation with which genesys-cloud-cx-as-code (Linux/Mac) or where genesys-cloud-cx-as-code (Windows).
  3. If using a virtual environment, ensure Node.js is accessible.

Error: “EACCES: permission denied”

Cause: The CLI attempts to write to a directory where the user lacks write permissions.

Fix:

  1. Ensure the output_dir specified in the Python script is writable by the current user.
  2. Avoid using root directories like /. Use a subdirectory like ./exports.

Error: Large Export Timeout

Cause: Organizations with hundreds of complex flows may hit API rate limits or timeout during the export process.

Fix:

  1. The CX as Code CLI has built-in retry logic for 429 errors.
  2. If the export fails repeatedly, break the export into smaller batches. However, the CLI does not currently support a “flow ID list” filter for exports.
  3. Monitor the Genesys Cloud API usage dashboard for rate limiting.
  4. Increase the Node.js memory limit if necessary: NODE_OPTIONS="--max-old-space-size=4096" genesys-cloud-cx-as-code export ...

Official References