Mastering Date Logic in Genesys Cloud Architect: DateTimeDiff vs GetDayOfWeek

Mastering Date Logic in Genesys Cloud Architect: DateTimeDiff vs GetDayOfWeek

What You Will Build

  • This tutorial demonstrates how to programmatically configure Genesys Cloud Architect flows using the POST /api/v2/architect/flows endpoint to implement precise date-based routing logic.
  • You will learn the distinct use cases for the DateTimeDiff function (calculating duration between timestamps) and GetDayOfWeek (extracting weekday identifiers) within the Genesys Cloud Expression Language.
  • The implementation uses Python with the genesys-cloud-py-client SDK to generate valid JSON payloads for conditional splits and queues based on temporal data.

Prerequisites

  • OAuth Client: A Genesys Cloud OAuth Client with the architect:flow:write and architect:flow:read scopes.
  • SDK Version: genesys-cloud-py-client version 134.0.0 or higher.
  • Language/Runtime: Python 3.9+.
  • External Dependencies: pip install genesys-cloud-py-client.
  • Conceptual Knowledge: Understanding of Genesys Cloud Architect Flow JSON structure, specifically the conditions block and the expression syntax.

Authentication Setup

Authentication is handled via the SDK’s built-in OAuth2 client credentials flow. The following code initializes the PureCloudPlatformClientV2 and obtains a valid access token. This token is automatically cached and refreshed by the SDK for subsequent API calls.

import os
from purerestclient import PureCloudPlatformClientV2

def get_platform_client():
    """
    Initialize and authenticate the Genesys Cloud Platform Client.
    """
    # Load credentials from environment variables
    client_id = os.getenv("GENESYS_CLIENT_ID")
    client_secret = os.getenv("GENESYS_CLIENT_SECRET")
    environment = os.getenv("GENESYS_ENVIRONMENT", "mypurecloud.com")

    if not client_id or not client_secret:
        raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET must be set.")

    # Initialize the platform client
    platform_client = PureCloudPlatformClientV2()
    
    # Configure the OAuth2 client credentials flow
    oauth_client = platform_client.oauth_client
    oauth_client.client_id = client_id
    oauth_client.client_secret = client_secret
    
    # Set the environment (e.g., mypurecloud.com, euw1.pure.cloud)
    oauth_client.host = f"https://{environment}"
    
    # Authenticate
    try:
        oauth_client.authenticate()
        return platform_client
    except Exception as e:
        raise RuntimeError(f"Authentication failed: {e}")

# Initialize the client
api_instance = get_platform_client().architect_api

Implementation

Step 1: Understanding the Expression Context

In Genesys Cloud Architect, logic is defined in JSON. Conditional splits use an expression field that evaluates to a boolean. The expression language supports specific functions for date manipulation.

Key Distinction:

  • DateTimeDiff: Calculates the difference between two date-time objects. It returns a numeric value representing the difference in a specified unit (seconds, minutes, hours, days). Use this when you need to compare duration or relative time (e.g., “Is the ticket older than 24 hours?”).
  • GetDayOfWeek: Extracts the day of the week from a date-time object. It returns an integer (1 for Sunday, 2 for Monday, etc., depending on the locale/configuration, but typically ISO standard or US standard). Use this when you need to route based on calendar days (e.g., “Is today Saturday?”).

Step 2: Constructing the DateTimeDiff Condition

Scenario: You want to route a conversation to a priority queue if the initial contact timestamp is more than 2 hours ago.

Logic:

  1. Get the current time: now()
  2. Get the start time of the conversation: interaction.startTime
  3. Calculate the difference in hours: DateTimeDiff(now(), interaction.startTime, "hours")
  4. Compare the result: > 2

JSON Payload Snippet:
The conditions object in the flow definition requires an expression string.

{
  "conditions": {
    "expression": "DateTimeDiff(now(), interaction.startTime, \"hours\") > 2"
  }
}

Python SDK Construction:
When building the flow via API, you must construct the Condition object correctly.

from purecloudplatformclientv2.models import Flow, Condition, Split

def create_time_based_split():
    """
    Creates a split condition that checks if the interaction 
    started more than 2 hours ago.
    """
    # Define the expression string
    # Note: In JSON, quotes inside strings must be escaped. 
    # In Python dicts, we handle this naturally.
    expression_str = 'DateTimeDiff(now(), interaction.startTime, "hours") > 2'
    
    # Create the Condition object
    condition = Condition(
        expression=expression_str,
        type="expression"
    )
    
    # Create the Split object
    split = Split(
        name="Is Old Interaction",
        conditions=[condition]
    )
    
    return split

Step 3: Constructing the GetDayOfWeek Condition

Scenario: You want to route calls to a weekend support queue if the current day is Saturday or Sunday.

Logic:

  1. Get the current time: now()
  2. Extract the day of the week: GetDayOfWeek(now())
  3. Check if the day is 1 (Sunday) or 7 (Saturday). Note: Genesys Cloud typically uses 1=Sunday, 2=Monday, …, 7=Saturday.
  4. Combine with logical OR: ||

JSON Payload Snippet:

{
  "conditions": {
    "expression": "GetDayOfWeek(now()) == 1 || GetDayOfWeek(now()) == 7"
  }
}

Python SDK Construction:

from purecloudplatformclientv2.models import Condition

def create_weekend_split():
    """
    Creates a split condition that checks if today is Saturday or Sunday.
    """
    # Define the expression string
    # 1 = Sunday, 7 = Saturday
    expression_str = 'GetDayOfWeek(now()) == 1 || GetDayOfWeek(now()) == 7'
    
    condition = Condition(
        expression=expression_str,
        type="expression"
    )
    
    return condition

Step 4: Assembling the Full Flow Definition

To deploy this logic, you must wrap the conditions in a complete Flow JSON structure. This example creates a simple flow that routes inbound calls based on the day of the week.

from purecloudplatformclientv2.models import (
    Flow, 
    FlowContact, 
    FlowRouting, 
    FlowRoutingQueue,
    Condition,
    Split
)

def build_date_logic_flow():
    """
    Builds a complete Flow definition that routes based on GetDayOfWeek.
    """
    # 1. Define the Weekend Condition
    weekend_condition = Condition(
        expression='GetDayOfWeek(now()) == 1 || GetDayOfWeek(now()) == 7',
        type="expression"
    )
    
    # 2. Define the Weekday Condition (Else branch)
    weekday_condition = Condition(
        expression='GetDayOfWeek(now()) != 1 && GetDayOfWeek(now()) != 7',
        type="expression"
    )

    # 3. Define the Splits
    weekend_split = Split(
        name="Weekend Support",
        conditions=[weekend_condition]
    )
    
    weekday_split = Split(
        name="Business Hours Support",
        conditions=[weekday_condition]
    )

    # 4. Define the Routing Queues (Placeholder IDs)
    # In production, replace these with actual Queue IDs from your org
    weekend_queue_id = "your-weekend-queue-id-here" 
    weekday_queue_id = "your-weekday-queue-id-here"

    # 5. Construct the Flow Object
    flow = Flow(
        name="Date Logic Demo Flow",
        description="Routes calls based on Day of Week using GetDayOfWeek",
        type="voice",
        contact=FlowContact(
            initial_contact_type="voice"
        ),
        routing=FlowRouting(
            queue=FlowRoutingQueue(
                id=weekday_queue_id # Default queue
            ),
            splits=[
                {
                    "split": weekend_split,
                    "queue": FlowRoutingQueue(id=weekend_queue_id)
                },
                {
                    "split": weekday_split,
                    "queue": FlowRoutingQueue(id=weekday_queue_id)
                }
            ]
        )
    )
    
    return flow

Step 5: Deploying the Flow via API

Now that the flow object is constructed, you send it to the POST /api/v2/architect/flows endpoint.

import json
from purecloudplatformclientv2.rest import ApiException

def deploy_flow(api_instance, flow):
    """
    Deploys the constructed flow to Genesys Cloud.
    """
    try:
        # Serialize the flow to JSON for debugging/logging if needed
        print("Deploying flow...")
        # print(json.dumps(flow.to_dict(), indent=2))
        
        # Make the API call
        response = api_instance.post_architect_flow(body=flow)
        
        print(f"Flow deployed successfully.")
        print(f"Flow ID: {response.id}")
        print(f"Flow Name: {response.name}")
        print(f"Flow Status: {response.status}")
        
        return response
        
    except ApiException as e:
        # Handle API errors
        print(f"Exception when calling ArchitectApi->post_architect_flow: {e}")
        if e.status == 400:
            print("Bad Request: Check the flow JSON structure and expression syntax.")
        elif e.status == 401:
            print("Unauthorized: Check your OAuth token.")
        elif e.status == 403:
            print("Forbidden: Check your OAuth scopes.")
        elif e.status == 429:
            print("Rate Limited: Wait and retry.")
        raise e

# Execute
if __name__ == "__main__":
    try:
        flow = build_date_logic_flow()
        deploy_flow(api_instance, flow)
    except Exception as e:
        print(f"Fatal error: {e}")

Complete Working Example

The following script combines authentication, flow construction, and deployment. It includes error handling and uses DateTimeDiff for a secondary condition example.

import os
import sys
from purerestclient import PureCloudPlatformClientV2
from purecloudplatformclientv2.models import (
    Flow, 
    FlowContact, 
    FlowRouting, 
    FlowRoutingQueue,
    Condition,
    Split
)
from purecloudplatformclientv2.rest import ApiException

def main():
    # 1. Authentication
    try:
        platform_client = PureCloudPlatformClientV2()
        oauth_client = platform_client.oauth_client
        oauth_client.client_id = os.getenv("GENESYS_CLIENT_ID")
        oauth_client.client_secret = os.getenv("GENESYS_CLIENT_SECRET")
        oauth_client.host = "https://mypurecloud.com"
        oauth_client.authenticate()
        
        architect_api = platform_client.architect_api
        
    except Exception as e:
        print(f"Authentication failed: {e}")
        sys.exit(1)

    # 2. Define Queue IDs
    # Replace these with actual IDs from your Genesys Cloud organization
    QUEUE_PRIORITY_ID = "YOUR_PRIORITY_QUEUE_ID"
    QUEUE_STANDARD_ID = "YOUR_STANDARD_QUEUE_ID"

    # 3. Define Conditions
    
    # Condition A: Is it the weekend? (GetDayOfWeek)
    # 1 = Sunday, 7 = Saturday
    weekend_expr = 'GetDayOfWeek(now()) == 1 || GetDayOfWeek(now()) == 7'
    weekend_condition = Condition(expression=weekend_expr, type="expression")
    
    # Condition B: Is the interaction older than 30 minutes? (DateTimeDiff)
    # This is a secondary check for priority routing during business hours
    old_interaction_expr = 'DateTimeDiff(now(), interaction.startTime, "minutes") > 30'
    old_condition = Condition(expression=old_interaction_expr, type="expression")

    # 4. Define Splits
    
    weekend_split = Split(name="Weekend", conditions=[weekend_condition])
    
    # For weekday, we might split further based on age
    # Note: In a real flow, you would nest splits or use a decision tree.
    # Here we simplify to two main branches for demonstration.
    weekday_split = Split(name="Weekday", conditions=[
        Condition(expression='GetDayOfWeek(now()) != 1 && GetDayOfWeek(now()) != 7', type="expression")
    ])

    # 5. Build Flow
    flow = Flow(
        name="Date Logic Tutorial Flow",
        description="Demonstrates GetDayOfWeek and DateTimeDiff",
        type="voice",
        contact=FlowContact(initial_contact_type="voice"),
        routing=FlowRouting(
            queue=FlowRoutingQueue(id=QUEUE_STANDARD_ID),
            splits=[
                {
                    "split": weekend_split,
                    "queue": FlowRoutingQueue(id=QUEUE_PRIORITY_ID) # Route weekends to priority
                },
                {
                    "split": weekday_split,
                    "queue": FlowRoutingQueue(id=QUEUE_STANDARD_ID) # Route weekdays to standard
                }
            ]
        )
    )

    # 6. Deploy
    try:
        response = architect_api.post_architect_flow(body=flow)
        print(f"Success: Flow '{response.name}' created with ID {response.id}")
        
    except ApiException as e:
        print(f"API Error {e.status}: {e.reason}")
        if e.body:
            print(f"Response Body: {e.body}")

if __name__ == "__main__":
    main()

Common Errors & Debugging

Error: 400 Bad Request - Invalid Expression

Cause: The expression string contains syntax errors, invalid function names, or incorrect argument types.
Fix:

  1. Verify function names are case-sensitive. Use DateTimeDiff not datetimeDiff.
  2. Ensure string arguments are quoted correctly. In JSON, use \"hours\". In Python dicts, use "hours".
  3. Check that interaction.startTime exists. If the contact type is not voice or chat, this attribute may not be available. Use interaction.createdTime as a fallback.

Debugging Code:

# Test the expression locally by printing the JSON payload
import json
payload = flow.to_dict()
print(json.dumps(payload, indent=2))
# Inspect the "expression" fields manually.

Error: 400 Bad Request - Flow Validation Failed

Cause: The flow structure is incomplete. For example, missing a default queue or having circular references.
Fix:

  1. Ensure every Split has a corresponding queue in the splits array.
  2. Ensure the routing.queue (default) is defined.
  3. Validate that Queue IDs exist. If you use a non-existent Queue ID, the API may return a 400 or 404 depending on the SDK version.

Error: Expression Returns Null

Cause: GetDayOfWeek(now()) or DateTimeDiff returns null because the input date is invalid or null.
Fix:

  1. Ensure now() is used correctly. It requires no arguments.
  2. Ensure interaction.startTime is not null. Add a null check in the expression if necessary:
    interaction.startTime != null && DateTimeDiff(now(), interaction.startTime, "hours") > 2
    

Error: 403 Forbidden

Cause: Missing OAuth scopes.
Fix: Ensure the OAuth client has architect:flow:write. If you only have architect:flow:read, you can fetch flows but not create or update them.

Official References