Skip to content

Python API Reference

This page provides comprehensive documentation for all SFAI Python API functions, including parameters, return values, and usage examples.

sfai.app - Application Management

init

Initialize a new SFAI application.

Parameters:

Name Type Description Default
app_name Optional[str]

Name of the application (defaults to directory name)

None
template str

Template to use for scaffolding (eg: fastapi_hello or flask_hello)

'fastapi_hello'
force bool

Whether to force reinitialization if already initialized

False

Returns:

Type Description
Dict[str, Any]

Dictionary with initialization status and details

Source code in sfai/app/init.py
def init(
    app_name: Optional[str] = None, template: str = "fastapi_hello", force: bool = False
) -> Dict[str, Any]:
    """
    Initialize a new SFAI application.

    Args:
        app_name: Name of the application (defaults to directory name)
        template: Template to use for scaffolding (eg: fastapi_hello or flask_hello)
        force: Whether to force reinitialization if already initialized

    Returns:
        Dictionary with initialization status and details
    """
    # Use current directory as target path
    target_path = Path.cwd()

    # Determine app name (use directory name if not provided)
    app_name = app_name or target_path.name

    # Check if already initialized
    context_file = target_path / CONTEXT_DIR / CONTEXT_FILE.name
    context_exists = context_file.exists()

    if context_exists and not force:
        return BaseResponse(
            success=False,
            error=(
                f"App '{app_name}' is already initialized. "
                f"Use force=True to reinitialize."
            ),
            app_name=app_name,
        )

    try:
        # Initialize the app with the specified template
        scaffold_hello_app(target_path, force, template)

        # Update environment and register app
        ctx_mgr = ContextManager()
        ctx_mgr.update_platform(
            platform="local",
            environment="default",
            app_name=app_name,
            values={"app_name": app_name},
        )
        ctx_mgr.register_app(app_name, str(target_path))

        return BaseResponse(
            success=True,
            app_name=app_name,
            message=(
                f"App '{app_name}' initialized successfully with template '{template}'"
            ),
        )
    except (ValueError, Exception) as e:
        return BaseResponse(success=False, error=f"Failed to initialize app: {e!s}")

Examples:

from sfai.app import init

# Initialize with default template
result = init()

# Initialize with specific template
result = init(app_name="my-api", template="fastapi_hello")

# Force reinitialize existing app
result = init(force=True, template="flask_hello")


deploy

Deploy an application to the configured environment.

Parameters:

Name Type Description Default
path str

Path to the application directory

'.'
platform Optional[str]

Platform to deploy to

None
environment Optional[str]

Environment to deploy to (uses active environment if None)

None
kwargs Any

Additional keyword arguments

{}

Returns:

Type Description
BaseResponse

Dictionary with deployment status and details

Source code in sfai/app/deploy.py
def deploy(
    path: str = ".",
    platform: Optional[str] = None,
    environment: Optional[str] = None,
    **kwargs: Any,
) -> BaseResponse:
    """
    Deploy an application to the configured environment.

    Args:
        path: Path to the application directory
        platform: Platform to deploy to
        environment: Environment to deploy to (uses active environment if None)
        kwargs: Additional keyword arguments

    Returns:
        Dictionary with deployment status and details
    """
    try:
        ctx_mgr = ContextManager()

        # determine the platform and environment to use
        response = determine_platform_and_environment(platform, environment)
        if not response.success:
            return response

        active_platform = response.platform
        active_environment = response.environment

        # Read the updated context for the determined platform and environment
        context = ctx_mgr.read_context(active_platform, active_environment)
        if not context:
            return BaseResponse(
                success=False,
                error=(
                    f"Failed to read context for platform '{active_platform}' "
                    f"and environment '{active_environment}'"
                ),
            )

        provider = PLATFORM_REGISTRY.get(active_platform)
        if not provider:
            return BaseResponse(
                success=False, error=f"Unsupported provider: {active_platform}"
            )

        result = provider.deploy(context=context, path=path, **kwargs)
        return result.with_update(
            app_name=context.get("app_name"),
            platform=active_platform,
            environment=active_environment,
        )
    except ValueError as e:
        return BaseResponse(success=False, error=f"Context validation error: {e!s}")

Examples:

from sfai.app import deploy

# Deploy to current platform
result = deploy()

# Deploy to specific platform
result = deploy(platform="heroku")

# Deploy from specific directory
result = deploy(path="./my-app")

# Deploy with additional parameters
result = deploy(platform="heroku", commit_message="Feature: Add new API endpoint")


open

Open the current app in the browser.

Parameters:

Name Type Description Default
path str

The path to open

'/docs'
port int

The port to open

8080
tunnel bool

Whether to use a tunnel

False
url str | None

The URL to open

None
platform Optional[str]

Platform to open from (optional)

None
environment Optional[str]

Environment to open from (defaults to "default")

None

Returns: A dictionary containing the result of the open operation

Source code in sfai/app/open.py
def open(
    path: str = "/docs",
    port: int = 8080,
    tunnel: bool = False,
    url: str | None = None,
    platform: Optional[str] = None,
    environment: Optional[str] = None,
) -> BaseResponse:
    """
    Open the current app in the browser.

    Args:
        path: The path to open
        port: The port to open
        tunnel: Whether to use a tunnel
        url: The URL to open
        platform: Platform to open from (optional)
        environment: Environment to open from (defaults to "default")
    Returns:
        A dictionary containing the result of the open operation
    """
    try:
        # Load current context
        ctx_mgr = ContextManager()

        # Determine the platform and environment to use
        response = determine_platform_and_environment(platform, environment)
        if not response.success:
            return response

        # Validate platform provider
        active_platform = response.platform
        active_environment = response.environment

        # Read the updated context for the determined platform and environment
        context = ctx_mgr.read_context(active_platform, active_environment)
        if not context:
            return BaseResponse(
                success=False,
                error=(
                    f"Failed to read context for platform '{active_platform}' "
                    f"and environment '{active_environment}'"
                ),
            )

        provider = PLATFORM_REGISTRY.get(active_platform)
        if not provider:
            return BaseResponse(
                success=False, error=f"Unsupported provider: {active_platform}"
            )

        # Validate tunnel requirements
        if tunnel and active_platform != "local":
            return BaseResponse(
                success=False,
                error="Tunneling is only supported in local environment.",
            )

        # Execute the open operation
        result = provider.open(context=context, path=path, url=url)

        # Return result with context metadata
        return result.with_update(
            app_name=context.get("app_name"),
            platform=active_platform,
            environment=active_environment,
        )

    except ValueError as e:
        return BaseResponse(success=False, error=f"Context validation error: {e!s}")

Examples:

from sfai.app import open

# Open app with default settings
result = open()

# Open specific path
result = open(path="/api/v1/health")

# Open with tunnel for public access
result = open(tunnel=True)

# Open on custom port
result = open(port=3000)

# Open custom URL
result = open(url="https://my-app.herokuapp.com")


status

Show the status of the current app from context.

Parameters:

Name Type Description Default
platform Optional[str]

Platform to get status from (optional)

None
environment Optional[str]

Environment to get status from (uses active environment if None)

None
Source code in sfai/app/status.py
def status(
    platform: Optional[str] = None, environment: Optional[str] = None
) -> BaseResponse:
    """
    Show the status of the current app from context.

    Args:
        platform: Platform to get status from (optional)
        environment: Environment to get status from (uses active environment if None)
    """
    try:
        ctx_mgr = ContextManager()

        # determine the platform and environment to use
        response = determine_platform_and_environment(platform, environment)
        if not response.success:
            return response

        active_platform = response.platform
        active_environment = response.environment

        # Read the updated context for the determined platform and environment
        context = ctx_mgr.read_context(active_platform, active_environment)
        if not context:
            return BaseResponse(
                success=False,
                error=(
                    f"Failed to read context for platform '{active_platform}' "
                    f"and environment '{active_environment}'"
                ),
            )

        provider = PLATFORM_REGISTRY.get(active_platform)
        if not provider:
            return BaseResponse(
                success=False, error=f"Unsupported provider: {active_platform}"
            )
        status_response = provider.status(context=context)
        return status_response.with_update(
            app_name=context.get("app_name"),
            platform=active_platform,
            environment=active_environment,
        )
    except ValueError as e:
        return BaseResponse(success=False, error=f"Context validation error: {e!s}")

Examples:

from sfai.app import status

# Show status from current platform
result = status()

# Show status from specific platform
result = status(platform="heroku")


logs

Show logs for the current app.

Parameters:

Name Type Description Default
platform Optional[str]

Platform to show logs for

None
environment Optional[str]

Environment to show logs for (uses active environment if None)

None

Returns:

Name Type Description
BaseResponse BaseResponse

Response object containing logs

Source code in sfai/app/logs.py
def logs(
    platform: Optional[str] = None, environment: Optional[str] = None
) -> BaseResponse:
    """
    Show logs for the current app.

    Args:
        platform: Platform to show logs for
        environment: Environment to show logs for (uses active environment if None)

    Returns:
        BaseResponse: Response object containing logs
    """
    try:
        ctx_mgr = ContextManager()

        # Determine which platform and environment to use
        response = determine_platform_and_environment(platform, environment)
        if not response.success:
            return response

        active_platform = response.platform
        active_environment = response.environment

        # Read the updated context for the determined platform and environment
        context = ctx_mgr.read_context(active_platform, active_environment)
        if not context:
            return BaseResponse(
                success=False,
                error=(
                    f"Failed to read context for platform '{active_platform}' "
                    f"and environment '{active_environment}'"
                ),
            )

        provider = PLATFORM_REGISTRY.get(active_platform)

        if not provider:
            return BaseResponse(
                success=False, error=f"Unsupported provider: {active_platform}"
            )

        logs_response = provider.logs(context=context)

        return logs_response.with_update(
            app_name=context.get("app_name"),
            platform=active_platform,
            environment=active_environment,
        )
    except ValueError as e:
        return BaseResponse(success=False, error=f"Context validation error: {e!s}")

Examples:

from sfai.app import logs

# Show logs from current platform
result = logs()

# Show logs from specific platform
result = logs(platform="eks")


delete

Delete the current app from the context.

Parameters:

Name Type Description Default
platform Optional[str]

Platform to delete from (optional)

None
environment Optional[str]

Environment to delete from (uses active environment if None)

None
Source code in sfai/app/delete.py
def delete(
    platform: Optional[str] = None, environment: Optional[str] = None
) -> BaseResponse:
    """
    Delete the current app from the context.

    Args:
        platform: Platform to delete from (optional)
        environment: Environment to delete from (uses active environment if None)
    """
    try:
        ctx_mgr = ContextManager()

        # determine the platform and environment to use
        response = determine_platform_and_environment(platform, environment)
        if not response.success:
            return response

        active_platform = response.platform
        active_environment = response.environment

        # Read the updated context for the determined platform and environment
        context = ctx_mgr.read_context(active_platform, active_environment)
        if not context:
            return BaseResponse(
                success=False,
                error=(
                    f"Failed to read context for platform '{active_platform}' "
                    f"and environment '{active_environment}'"
                ),
            )
        provider = PLATFORM_REGISTRY.get(active_platform)

        if not provider:
            return BaseResponse(
                success=False, error=f"Unsupported provider: {active_platform}"
            )

        delete_response = provider.delete(context=context)
        return delete_response.with_update(
            app_name=context.get("app_name"),
            platform=active_platform,
            environment=active_environment,
        )
    except ValueError as e:
        return BaseResponse(success=False, error=f"Context validation error: {e!s}")

Examples:

from sfai.app import delete

# Delete from current platform
result = delete()

# Delete from specific platform
result = delete(platform="heroku")


Source code in sfai/app/context.py
def get_context() -> BaseResponse:
    try:
        context = ctx_mgr.read_context()
        if not context:
            return BaseResponse(
                success=False,
                app_name=None,
                error="No app context found",
            )
        return BaseResponse(
            success=True,
            app_name=context.get("app_name"),
            platform=context.get("active_platform"),
            environment=context.get("active_environment"),
            context=context,
        )
    except ValueError as e:
        return BaseResponse(
            success=False,
            app_name=None,
            error=str(e),
        )

Examples:

from sfai.app import get_context

# Get current context
result = get_context()
if result.success:
    print(f"App: {result.app_name}")
    print(f"Platform: {result.platform}")


Delete the current context

Source code in sfai/app/context.py
def delete_context() -> BaseResponse:
    """
    Delete the current context
    """
    try:
        context = ctx_mgr.read_context()
        if not context:
            return BaseResponse(
                success=False,
                app_name=None,
                error="No app context found",
            )
        app_name = context.get("app_name")
        if CONTEXT_FILE.exists():
            CONTEXT_FILE.unlink()
            ctx_mgr.unregister_app(app_name)
            return BaseResponse(
                success=True,
                app_name=app_name,
                message=f"Context for {app_name} deleted and unregistered",
            )
        else:
            return BaseResponse(
                success=False,
                app_name=app_name,
                error=f"Context for {app_name} not found",
            )
    except ValueError as e:
        return BaseResponse(
            success=False,
            app_name=app_name,
            error=str(e),
        )

Examples:

from sfai.app import delete_context

# Delete current context
result = delete_context()


Examples:

from sfai.app import publish

# Publish to MuleSoft with specific parameters
result = publish(
    service="mulesoft",
    profile="production",
    endpoint_uri="https://api.example.com",
    gateway_id="abc123",
    gateway_version="1.0.0"
)

# Publish with tags
result = publish(
    service="mulesoft",
    name="my-api",
    tags=["api", "production", "v1"]
)


Source code in sfai/app/helm.py
def download_helm_chart() -> BaseResponse:
    try:
        ctx_mgr = ContextManager()
        context = ctx_mgr.read_context()
        if not context:
            return BaseResponse(
                success=False,
                app_name=None,
                error="No app context found",
            )
        chart_path = CHARTS_PATH
        if not chart_path.exists():
            return BaseResponse(
                success=False,
                error="Helm chart not found",
            )

        # Download the chart
        destination_path = Path("./helm-chart")
        if destination_path.exists():
            shutil.rmtree(destination_path)
        shutil.copytree(chart_path, destination_path)

        # Show warning about local chart usage
        console.print(
            f"{WARNING_EMOJI} [{WARNING_COLOR}]Custom helm chart found. This "
            f"chart folder will be used for future deployments. Delete "
            f"./helm-chart to use the default chart.[/]"
        )

        return BaseResponse(
            success=True,
            message="Helm chart downloaded successfully",
            app_name=context.get("app_name"),
            platform=context.get("platform"),
        )
    except ValueError as e:
        return BaseResponse(success=False, error=f"Context validation error: {e!s}")

Examples:

from sfai.app import download_helm_chart

# Download Helm chart for current app
result = download_helm_chart()


sfai.config - Service Configuration

init

Initialize configuration for a service.

Parameters:

Name Type Description Default
service str

Service name (e.g., "mulesoft")

required
credentials

Dictionary of credentials for the service

required
profile_name str

Profile name to store credentials under

'default'
env Optional[str]

Environment to set as active (uses current if None)

None
**kwargs

pass values directly to the service provider

{}

Returns:

Type Description
BaseResponse

BaseResponse

Source code in sfai/config/init.py
def init(
    service: str,
    config: Optional[Dict[str, Any]] = None,
    profile_name: str = "default",
    env: Optional[str] = None,
    **kwargs,
) -> BaseResponse:
    """
    Initialize configuration for a service.

    Args:
        service: Service name (e.g., "mulesoft")
        credentials: Dictionary of credentials for the service
        profile_name: Profile name to store credentials under
        env: Environment to set as active (uses current if None)
        **kwargs: pass values directly to the service provider

    Returns:
        BaseResponse
    """
    ctx_mgr = ContextManager()

    # Read current context to get app info if needed
    context = ctx_mgr.read_context()
    if not context:
        return BaseResponse(
            success=False, error="No app context found. Initialize an app first."
        )

    app_name = context.get("app_name")
    current_platform = env or context.get("active_platform")

    if config is None and not kwargs:
        return BaseResponse(success=False, error="No configuration provided.")
    config = config or kwargs
    if not app_name or not current_platform:
        return BaseResponse(
            success=False, error="App name or platform missing in context."
        )

    # Validate credentials
    result = validate(service, config)
    if not result.success:
        return result.with_update(
            service=service,
            profile_name=profile_name,
        )

    try:
        # Save the service profile
        ctx_mgr.add_service_profile(service, profile_name, config)

        # Update the environment to use this profile
        ctx_mgr.update_platform(current_platform, {service: {"profile": profile_name}})

        return BaseResponse(
            success=True,
            service=service,
            profile_name=profile_name,
        )
    except ValueError as e:
        return BaseResponse(success=False, error=f"Failed to save credentials: {e!s}")

Examples:

from sfai.config import init

# Initialize MuleSoft configuration
result = init(
    service="mulesoft",
    profile_name="production",
    org_id="abc123",
    environment_id="def456",
    client_id="ghi789",
    client_secret="secret123"
)

# Initialize with config dictionary
config = {
    "org_id": "abc123",
    "client_id": "ghi789",
    "client_secret": "secret123"
}
result = init(service="mulesoft", config=config)


update

Update configuration for a service.

Parameters:

Name Type Description Default
service str

Service name

required
updates Dict[str, Any]

New values to update

required
profile_name str

Profile name to update

'default'

Returns:

Type Description
BaseResponse

BaseResponse

Source code in sfai/config/update.py
def update(
    service: str, updates: Dict[str, Any], profile_name: str = "default"
) -> BaseResponse:
    """
    Update configuration for a service.

    Args:
        service: Service name
        updates: New values to update
        profile_name: Profile name to update

    Returns:
        BaseResponse
    """
    ctx_mgr = ContextManager()

    # Check if service and profile are valid
    result = profile_exists(service, profile_name)
    if not result.success:
        return result.with_update(
            service=service,
            profile_name=profile_name,
        )

    try:
        ctx_mgr.update_service_profile(service, profile_name, updates)
        return BaseResponse(
            success=True,
            service=service,
            profile_name=profile_name,
            updated_fields=list(updates.keys()),
        )
    except ValueError as e:
        return BaseResponse(
            success=False, error=f"Failed to update configuration: {e!s}"
        )

Examples:

from sfai.config import update

# Update specific fields
result = update(
    service="mulesoft",
    profile_name="production",
    updates={"client_secret": "new-secret"}
)

# Update multiple fields
result = update(
    service="mulesoft",
    updates={
        "org_id": "new-org",
        "environment_id": "new-env"
    }
)


list

List all profiles for one or all services.

Parameters:

Name Type Description Default
service Optional[str]

Service name, or None to list all services

None

Returns:

Type Description
BaseResponse

BaseResponse with operation result and profiles list

Source code in sfai/config/list.py
def list(service: Optional[str] = None) -> BaseResponse:
    """
    List all profiles for one or all services.

    Args:
        service: Service name, or None to list all services

    Returns:
        BaseResponse with operation result and profiles list
    """
    ctx_mgr = ContextManager()

    try:
        if service:
            # Use the ContextManager method for single service
            profiles = ctx_mgr.list_service_profiles(service)
            if not profiles:
                return BaseResponse(
                    success=False, error=f"No profiles found for service: {service}"
                )
            return BaseResponse(success=True, service=service, profiles=profiles)
        else:
            # Get all services and their profiles
            context = ctx_mgr._load_json(ctx_mgr.global_context_file)
            all_profiles = context.get("service_profiles", {})

            if not all_profiles:
                return BaseResponse(success=True, profiles={})

            result = {}
            for svc in all_profiles.keys():
                result[svc] = ctx_mgr.list_service_profiles(svc)

            return BaseResponse(success=True, profiles=result)
    except Exception as e:
        return BaseResponse(success=False, error=f"Failed to list profiles: {e!s}")

Examples:

from sfai.config import list

# List all profiles
result = list()

# List profiles for specific service
result = list(service="mulesoft")


view

View details of a service profile.

Parameters:

Name Type Description Default
service str

Service name

required
profile_name str

Profile name to view

'default'

Returns:

Type Description
BaseResponse

BaseResponse

Source code in sfai/config/view.py
def view(service: str, profile_name: str = "default") -> BaseResponse:
    """
    View details of a service profile.

    Args:
        service: Service name
        profile_name: Profile name to view

    Returns:
        BaseResponse
    """
    ctx_mgr = ContextManager()

    # Check if profile exists
    exists, error = profile_exists(service, profile_name)
    if not exists:
        return BaseResponse(
            success=False,
            error=error,
            service=service,
            profile_name=profile_name,
        )

    # Get the profile
    profile = ctx_mgr.get_service_profile(service, profile_name)

    # Create a safe version with masked secrets
    safe_profile = {}
    for key, value in profile.items():
        if any(s in key.lower() for s in ["secret", "password", "key"]):
            # Mask the secret value, showing just the first and last character
            safe_profile[key] = (
                f"{value[0]}{'*' * (len(str(value)) - 2)}{value[-1]}"
                if len(str(value)) > 4
                else "****"
            )
        else:
            safe_profile[key] = value
    return BaseResponse(
        success=True,
        message=f"Profile '{profile_name}' for service '{service}' is shown below",
        profile_name=profile_name,
        service=service,
        data=safe_profile,
    )

Examples:

from sfai.config import view

# View default profile
result = view(service="mulesoft")

# View specific profile
result = view(service="mulesoft", profile_name="production")


delete

Delete a service profile.

Parameters:

Name Type Description Default
service str

Service name

required
profile_name str

Profile name to delete

'default'

Returns:

Type Description
BaseResponse

BaseResponse

Source code in sfai/config/delete.py
def delete(service: str, profile_name: str = "default") -> BaseResponse:
    """
    Delete a service profile.

    Args:
        service: Service name
        profile_name: Profile name to delete

    Returns:
        BaseResponse
    """
    ctx_mgr = ContextManager()

    # Check if profile exists
    exists, error = profile_exists(service, profile_name)
    if not exists:
        return BaseResponse(success=False, error=error)

    try:
        # Delete the profile
        ctx_mgr.delete_service_profile(service, profile_name)

        # Check if this profile is referenced in any environments
        context = ctx_mgr._load_json(ctx_mgr.context_file)
        environments = context.get("environments", {})

        # For each environment, check if it uses this profile
        for env_name, env_data in environments.items():
            if service in env_data and env_data[service].get("profile") == profile_name:
                # Remove the profile reference from this environment
                ctx_mgr.clear_platform_keys(env_name, [service])

        return BaseResponse(
            success=True,
            service=service,
            profile_name=profile_name,
            message=(
                f"Profile '{profile_name}' for service '{service}' has been deleted."
            ),
        )
    except Exception as e:
        return BaseResponse(success=False, error=f"Failed to delete profile: {e!s}")

Examples:

from sfai.config import delete

# Delete default profile
result = delete(service="mulesoft")

# Delete specific profile
result = delete(service="mulesoft", profile_name="production")


sfai.core - Core Models

BaseResponse

Standard response model for all API calls.

Attributes: - success (bool): Operation success status - message (str): Human-readable message - error (Optional[str]): Error message if success=False - Additional fields specific to each operation

Methods: - with_update(**kwargs): Create a new response with additional fields

Example:

from sfai.app import init

result = init()
print(f"Success: {result.success}")
print(f"Message: {result.message}")
if hasattr(result, 'app_name'):
    print(f"App Name: {result.app_name}")