How to Create Bright Pattern Tasks from a Salesforce Flow
You can trigger the creation of Bright Pattern tasks using Salesforce Flow and a custom Apex action. This guide provides an example for configuring an Apex action and invoking it from a Salesforce Flow
Prerequisites
- Administrator access to your Salesforce organization.
- Administrator access to your Bright Pattern Contact Center.
- Configured a Bright Pattern user for API usage, with an API Secret and the Use Task Routing API user privilege enabled.
- A configured Task Scenario Entry in Bright Pattern, and its Unique Identifier to use as the
taskLaunchPointId
.
Step 1: Securely Store API Configurations
A single Protected Custom Setting will hold all the necessary configuration. This keeps secrets secure and makes the integration easy to manage from one location.
- In Salesforce Setup, search for and select Custom Settings.
- Click New.
- Enter the following details:
- Label:
Bright Pattern Config
- Object Name:
Bright_Pattern_Config
- Setting Type:
Hierarchy
- Visibility:
Protected
- Label:
- Click Save.
- On the Custom Setting page, in the Custom Fields section, click New and add the following fields:
- Data Type:
Text
, Field Label:Client ID (Username)
, Length: 255 - Data Type:
Text
, Field Label:Client Secret (API Secret)
, Length: 255 - Data Type:
Text
, Field Label:Task Launch Point ID
, Length: 255 - Data Type:
URL
, Field Label:Token Endpoint
, Length: 255 - Data Type:
URL
, Field Label:Task API Endpoint
, Length: 255
- Data Type:
- After creating the fields, click the Manage button at the top of the
Bright Pattern Config
page. - Click New (at the top, next to "Default Organization Level Value").
- Populate the fields with your Bright Pattern contact center details:
- Client ID (Username): The username of the Bright Pattern user.
- Client Secret (API Secret): API Secret of the Bright Pattern user.
- Task Launch Point ID: The Unique Identifier from your Task Scenario Entry in Bright Pattern.
- Token Endpoint: The URL for the get access token endpoint of your contact center, of the format
https://<your-contact-center>.brightpattern.com/configapi/v2/oauth/token
. - Task API Endpoint: The URL for the queue task endpoint of your contact center, of the format
https://<your-contact-center>.brightpattern.com/taskroutingapi/v1/task
.
- Click Save.
Step 2: Create the Invocable Apex Class
This Apex class contains the logic to create a task in Bright Pattern. It retrieves all configuration from the Protected Custom Setting created in the previous step, including the taskLaunchPointId
, to handle authentication and routing securely.
- In Salesforce Setup, search for and select Apex Classes.
- Click New and use the following code as an example for creating a class:
/* This class contains an Invocable Apex Action for a Salesforce Flow. Its purpose is to queue a task in the Bright Pattern system by making a callout to their API. An important security note: The user running the Flow that calls this Apex action must have the appropriate permissions to the Bright_Pattern_Config__c custom setting. */ public with sharing class BrightPatternTaskController { // This is a custom exception class to provide more specific error details from this controller. public class BrightPatternException extends Exception {} // This inner class defines the input variables that will be exposed in the Flow Builder. // The Flow will pass data into an instance of this class. public class FlowRequest { @InvocableVariable(label="Case ID for Screenpop" required=true) public String caseId; @InvocableVariable(label="Case Number" required=true) public String caseNumber; @InvocableVariable(label="Contact ID" required=true) public String contactId; @InvocableVariable(label="Task Subject" required=true) public String subject; @InvocableVariable(label="Task Priority") public String priority; } /* This method is exposed to the Flow Builder as an Apex Action. It takes a list of requests from the Flow and queues a corresponding task in Bright Pattern. */ @InvocableMethod(label="Queue Bright Pattern Task", description="Queues a task in Bright Pattern via the API." category="Bright Pattern") public static void queueTaskInBrightPattern(List<FlowRequest> requests) { // Retrieve all configuration from the Protected Custom Setting. Bright_Pattern_Config__c bpConfig = Bright_Pattern_Config__c.getOrgDefaults(); // Check for valid configuration and throw a clear error if anything is missing. // This provides immediate feedback to the Flow administrator if the setup is incomplete. if (bpConfig == null || String.isBlank(bpConfig.Task_Launch_Point_ID__c) || String.isBlank(bpConfig.Task_API_Endpoint__c) || String.isBlank(bpConfig.Token_Endpoint__c) || String.isBlank(bpConfig.Client_ID__c) || String.isBlank(bpConfig.Client_Secret__c)) { throw new AuraHandledException("Bright Pattern configuration is missing or incomplete in Custom Settings. Please check the configuration."); } try { // Get the access token once for this entire transaction. String accessToken = getAccessToken(bpConfig); if (String.isBlank(accessToken)) { // Throw an exception that the Flow can handle if the token request fails. throw new BrightPatternException("Failed to obtain a Bright Pattern Access Token."); } // Even though we often expect one request per invocation from a Flow, // we loop through the list, as this is the best practice for Invocable Methods. for (FlowRequest req : requests) { Http http = new Http(); HttpRequest apiRequest = new HttpRequest(); apiRequest.setEndpoint(bpConfig.Task_API_Endpoint__c); apiRequest.setMethod("POST"); apiRequest.setHeader("Authorization", "Bearer " + accessToken); apiRequest.setHeader("Content-Type", "application/json;charset=UTF-8"); // Construct the request body from the Flow inputs. Map<String, Object> bodyMap = new Map<String, Object>{ "taskLaunchPointId" => bpConfig.Task_Launch_Point_ID__c, "extTaskId" => req.caseNumber, "extContactId" => req.contactId, "priority" => req.priority, "taskInfo" => new Map<String, String>{ "subject" => req.subject }, "screenpop" => "SHOW_OBJECT:" + req.caseId + ":Case" }; apiRequest.setBody(JSON.serialize(bodyMap)); HttpResponse response = http.send(apiRequest); // Check the response and throw an exception on failure. // This will halt the Flow and display an error, preventing silent failures. if (response.getStatusCode() != 200) { String errorMessage = "Failed to queue task in Bright Pattern. Status: " + response.getStatus() + ". Body: " + response.getBody(); System.debug(errorMessage); throw new BrightPatternException(errorMessage); } else { System.debug("Successfully queued task: " + response.getBody()); } } } catch (Exception e) { // This is a centralized exception handler. // It catches any exceptions thrown from the logic above (like CalloutException or our custom BrightPatternException). // It then re-throws them as an AuraHandledException to make them visible in the Flow's fault path. System.debug("An error occurred in BrightPatternTaskController: " + e.getMessage() + " Stacktrace: " + e.getStackTraceString()); throw new AuraHandledException(e.getMessage()); } } // This is a helper method to get the access token using securely stored credentials. // It takes the Bright Pattern configuration custom setting as its input. // It returns the access token string. private static String getAccessToken(Bright_Pattern_Config__c config) { HttpRequest tokenRequest = new HttpRequest(); tokenRequest.setEndpoint(config.Token_Endpoint__c); tokenRequest.setMethod("POST"); tokenRequest.setHeader("Content-Type", "application/x-www-form-urlencoded"); // The scope is derived from the Token Endpoint URL. For Bright Pattern, this is the tenant URL. String tenantUrl = new URL(config.Token_Endpoint__c).getHost(); String requestBody = "grant_type=client_credentials" + "&client_id=" + EncodingUtil.urlEncode(config.Client_ID__c, "UTF-8") + "&client_secret=" + EncodingUtil.urlEncode(config.Client_Secret__c, "UTF-8") + "&scope=" + EncodingUtil.urlEncode(tenantUrl, "UTF-8"); tokenRequest.setBody(requestBody); Http http = new Http(); HttpResponse tokenResponse = http.send(tokenRequest); if (tokenResponse.getStatusCode() == 200) { Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(tokenResponse.getBody()); return (String) result.get("access_token"); } else { // Log the detailed error but return null so it can be handled by the calling method. System.debug("Token request failed. Status: " + tokenResponse.getStatus() + ". Body: " + tokenResponse.getBody()); return null; } } }
- Save the class.
Step 3: Create the Salesforce Flow
The Flow defines the business process that will trigger the Apex action. This example shows how to use a record-triggered flow to create a task whenever a new Case is created or updated.
- In Setup, search for and select Flows.
- Click New Flow and select Record-Triggered Flow.
- Configure the trigger:
- Object:
Case
- Trigger the Flow When:
A record is created
- Optimize the Flow for:
Actions and Related Records
- Object:
- Click Done.
- On the Flow canvas, click the
+
icon and select the Action element. - In the Action search box, select the Apex category and choose Queue Bright Pattern Task.
- Fill in the action details.
- Label: Give the action a descriptive name, like
Create BP Task for New Case
. - Map Input Values: Map the fields from the triggering Case record (
$Record
) to the inputs of your Apex Action.- Case ID for Screenpop:
$Record.Id
- Contact ID:
$Record.ContactId
- Case Number:
$Record.CaseNumber
- Task Subject:
$Record.Subject
- Task Priority: Optionally, set a Queueing priority to override the priority set in the Task Scenario Entry.
- Case ID for Screenpop:
- Label: Give the action a descriptive name, like
- Click Done.
- Click Save, give your Flow a name (e.g.,
New Case to Bright Pattern Task
), and click Activate. - When a new record is created, a task should be queued automatically in Agent Desktop.
< Previous