Authored by Mark Beauchamp, Manuel Corujo Ferro
Introduction
This guide is intended to be used as a starting point whenever you are requested, in a project, to integrate Pega with a Salesforce environment. For additional information you can refer to Salesforce documentation in the References section.
Salesforce provides an API that allows to fetch information from their data model and, in some cases, update it.
On the other hand, Salesforce can use Pega API, Mashup, and Pega Extender for Salesforce to handle integration in the other direction.
This is a quick guide of the resources available to integrate Pega and Salesforce. See the References section for more information.
Use Pega from Salesforce
Pega Extender for Salesforce
Case Management can be used from Salesforce by using the Pega Extender for Salesforce component.
https://www.pega.com/es/insights/resources/pega-extender-salesforce-data-sheet
Pega Web Mashup
You can display a Pega application inside Salesforce by embedding Pega Web Mashup using a lighting component. Mashup allows communication in both directions so information can travel from Pega to Salesforce and from Salesforce to Pega.
Pega API + DX API
You can use all Pega capabilities with the Pega API.
- Fetch information with Pega REST API.
- Use Case Management through both Pega REST API and DX API.
Salesforce Data Model
In a Salesforce app you can use out-of-the-box (OOTB) objects and custom objects. Similarly to Pega Objects, they can have instances. Salesforce objects also have defined properties, and sections. Both OOTB and custom objects can be referred by using Salesforce API, main difference being the naming convention, as custom objects and fields have a __c suffix.
Objects include fields that can have different types, both simple (string, number, date…) and complex (currency, picklist…).
Salesforce REST API
Salesforce provides a powerful REST API. It provides access to Salesforce without using their user interface.
URIs
REST API URIs are very similar from resource to resource, with the following structure:
https://MyDomain.my.salesforce.com/services/data/vXX.XX/resource/
- MyDomain: Corresponds to your client’s domain.
- vXX.XX: API version.
- Resource: Method used to recover.
Authorization
To use the Salesforce REST API, every call needs to include an authorization code. Authorization uses OAuth 2.0. Please refer to the configuration example at the end.
The token can be obtained by performing a REST call to token service. This service uses existing user and security credentials to obtain a token that can be later used in calls.
Request:
- grant_type: you can indicate the method to use to validate user credentials. The “password” method allows you to directly send username and password. However other methods are allowed depending on the need.
- client_id, client_secret: A connected app needs to be created in salesforce to use Oauth 2.0 in REST API. When configuring the connected app, client ID and secret will be generated. This information is needed when obtaining the token.
- username, password: User credentials.
- redirect_uri: OAuth 2.0 redirect URI. It may vary depending on your connected app configuration.
Response:
{ "access_token": "00D0Q0000000MWt!ARMAQKRpmQbs4kkv5G1k.FuAZ3.kPVEqb5IU3GfzVcJQ8xtD9Yk5R3TeY2eclyZKm5p6ynw6IHL72xVTqAb_u91Q0zMxdCua", "instance_url": "https://xxxxxxx--www.my.salesforce.com", "id": "https://test.salesforce.com/id/11D0F0033000hWttAM/1022V030500fi4bQeQ", "token_type": "Bearer", "issued_at": "1645000283087", "signature": "12349q7x123d2wMDtuEUdfeR0YidTmZd8FmNTASi323u=" }
The request property access_token and token_type contains the header authorization value that you need to set on your REST API calls.
Objects
This resource retrieves information from Salesforce Data Model Objects. This includes both information about the object itself (metadata, and links to object resources) and instances of the object.
URI
Resource key to use is “sobjects”. After the resource key, the object to get information from is indicated. After the object, you can indicate what kind of information you want or object ID to retrieve an instance.
https://MyDomain.salesforce.com/services/data/v53.0/sobjects/Object/
Retrieve Metadata
By not passing anything to the URL, the service returns all metadata of the object, along with recents and possible URLs to query the object data. With those URLs it is possible to get an object instance, obtain information of the existing fields of the object by using describe, or fetch Salesforce layouts and views.
{ "objectDescribe": { "activateable": false, "createable": false, "custom": false, "customSetting": false, "deepCloneable": false, "deletable": false, "deprecatedAndHidden": false, "feedEnabled": true, "hasSubtypes": false, "isInterface": false, "isSubtype": false, "keyPrefix": "001", "label": "Account", "labelPlural": "Accounts", "layoutable": true, "mergeable": false, "mruEnabled": true, "name": "Account", "queryable": true, "replicateable": true, "retrieveable": true, "searchable": true, "triggerable": true, "undeletable": false, "updateable": false, "urls": { "compactLayouts": "/services/data/v49.0/sobjects/Account/describe/compactLayouts", "rowTemplate": "/services/data/v49.0/sobjects/Account/{ID}", "approvalLayouts": "/services/data/v49.0/sobjects/Account/describe/approvalLayouts", "listviews": "/services/data/v49.0/sobjects/Account/listviews", "describe": "/services/data/v49.0/sobjects/Account/describe", "quickActions": "/services/data/v49.0/sobjects/Account/quickActions", "layouts": "/services/data/v49.0/sobjects/Account/describe/layouts", "sobject": "/services/data/v49.0/sobjects/Account" } }, "recentItems": [ { "attributes": { "type": "Account", "url": "/services/data/v49.0/sobjects/Account/0011w00000rnxdsAAA" }, "Id": "1111w012300rnsdsABA", "Name": "Test Account 1" }, { "attributes": { "type": "Account", "url": "/services/data/v49.0/sobjects/Account/0011w00000vL3ktAAC" }, "Id": "1341r12340vL3ktAAT", "Name": " Test Account 1" } ] }
Object Describe
Adding keyword describe to the URL allows to fetch all object fields and possible values on picklists. For example sobjects/Account/describe will return all the fields along with their format and possible values, if it is a dropdown (called picklist in Salesforce). For example (truncated fields to save space):
{ "aggregatable": true, "aiPredictionField": false, "autoNumber": false, "byteLength": 30, "compoundFieldName": "BillingAddress", "controllerName": "BillingCountryCode", "picklistValues": [ { "active": true, "defaultValue": false, "label": "Aargau", "validFor": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA", "value": "AG" }, { "active": true, "defaultValue": false, "label": "Acre", "validFor": "AAAAAQAA", "value": "AC" } ], },
Instances
By adding the ID of the object to search after the object, you can recover an entire instance of the given object. For example sobjects/Account/1010T003G1R43o2Q9R returns the following response:
{ "attributes": { "type": "Account", "url": "/services/data/v49.0/sobjects/Account/0011w00000rnxdsAAA" }, "Id": "AAAAr00312rntfgAAA", "IsDeleted": false, "MasterRecordId": null, … }(Response is truncated for space purposes)
It is possible to create, update and delete records by using REST methods, POST, PATCH and DELETE.
- CREATE using POST
- URL sobjects/Account/
- Body: JSON with fields to set, for example:
{ "Name" : "New Account" }
- Response:
{ "id"": "AAAAr00312rntfgAAA", "errors"s: [ ], "success"s: true }
- Update using PATCH
- URL sobjects/Account/ID
- Body: JSON with fields to update, for example:
{ "BillingCity" : "Madrid" }
- Response: none returned
- Delete using DELETE
- URL sobjects/Account/ID
- Body: none
- Response: none returned
Recently Viewed
This resource allows recovery of recent viewed objects from user. This is restricted to the user used in Oauth 2.0 authorization, you can’t access another user’s recent list.
URI
Resource key to use is “recent”. The SOSL (Salesforce Object Search Language) query string includes parameter limit=n to set maximum number of records returned.
https://MyDomain.salesforce.com/services/data/v53.0/recent/?limit=5
Response
Response JSON contains Attributes type and URL, ID, Name of the recently viewed objects for the authorized user.
[ { "attributes": { "type": "Account", "url": "/services/data/v49.0/sobjects/Account/AAAAr00312rntfgAAA" }, "Id": "AAAAr00312rntfgAAA", "Name": "Test Account 1" }, { "attributes": { "type": "User", "url": "/services/data/v49.0/sobjects/User/AAAAr00312rntfgAAA" }, "Id": "AAAAr00312rntfgRRR", "Name": "Test User 1" } ]
Query
Use query resource to execute a SOQL (Salesforce Object Query Language) query that returns results in a single response. SOQL is a SQL like language, it allows selection of fields and filter results including a where condition. Use SOQL when you know which objects data resides in and you want to:
- Retrieve data from a single object or from multiple objects that are related to one another
- Count the number of records that meet specified criteria
- Sort results as part of the query
- Retrieve data from the number, date, or checkbox fields
URI
Resource key to use is “query”. The SOSL query string is included as URI parameter “q”
https://MyDomain.salesforce.com/services/data/v53.0/query/?q=SELECT+name+from+Account
SOSL Query String
The use of * wildcard is not allowed. This means you need to know beforehand the fields you want to include in response. Please note that when used in query you need to URL Encode the query.
SOQL does not support advanced SQL command features, so the query is limited. However, it is possible to use an Alias notation to recover information from other tables (similar to Join) that are logically linked (for example an Account is owned by a User).
For example, you can recover User Role information when querying User object by using UserRole alias:
Select ID, Username, LastName, FirstName, MiddleName, Name, Email, UserRoleId, UserRole.Name From User
It is possible to use Limit keyword to restrict the number of records returned by query, also ORDER BY can be used. The following query will return the first 5 accounts only, ordered by name.
Select id,Name from Account LIMIT 5 ORDER BY Name ASC
Response
Response JSON contains the records corresponding to the query along with attributes, size, and status of the call. Following example for query “?q=Select+Id,Name+From+Account+LIMIT+1”
{ "totalSize": 1, "done": true, "records": [ { "attributes": { "type": "Account", "url": "/services/data/v49.0/sobjects/Account/AAAAr00312rntfgAAA" }, "Id": "AAAAr00312rntfgAAA", "Name": "EXAMPLE TEST ACCOUNT" } ] }
Attributes normally return type and URL of Object that can be used to retrieve the entire record.
Search
Use search resource to execute an SOSL query that returns text-based filtered results in a single response. This resource allows you to use the Salesforce search engine which in turn makes text-based search more effective. It is possible to use the LIKE command in SOQL but it is inefficient. Instead you can use SOSL. Use SOQL when you do not know in which objects data resides and you want to:
- Retrieve data for a specific term that you know exists within a field. Because SOSL can tokenize multiple terms within a field and build a search index from this, SOSL searches are faster and can return more relevant results.
- Retrieve multiple objects and fields efficiently where the objects might or might not be related to one another.
- Retrieve data for a particular division in an organization using the divisions feature.
- Retrieve data that’s in Chinese, Japanese, Korean, or Thai. Morphological tokenization for CJKT terms helps ensure accurate results.
URI
Resource key to use is “search”. The SOQL search string is included as URI parameter “q”
https://MyDomain.salesforce.com/services/data/v53.0/search/?q=FIND+{*TEXT*}+IN+ALL+FIELDS+RETURNING+Account(id,Name)WHERE+Id=’XXX’
SOSL Search String Syntax
FIND {Search query} – Specify the text you want to search. Length must be longer than 2. You can use wild cards.
IN SearchGroup – Specify the scope of the search, possible values: ALL FIELDS, NAME FIELDS, EMAIL FIELDS, PHONE FIELDS, SIDEBAR FIELDS. Defaulted to ALL FIELDS.
RETURNING FieldSpec (fields to return) – Information to return back. Search engine searches in all objects in the system by default. You can restrict the search to specific objects and the fields to return back. If you do not specify any fields in the list, system will only return ID.
It is possible to use the Limit keyword to restrict the number of records returned by query, also ORDER BY can be used. The following query will return the first 5 accounts only, ordered by name.
Select id,Name from Account LIMIT 5 ORDER BY Name ASC
OFFSET n – It is possible to paginate results by using offset and limit. Offset starts in 0, so in the case you want to paginate, you can do it by setting the limit to N and Offset to (N+1) * (page-1).
Response
Response contains the records corresponding to the search along with attributes, size and status of the call. Following example for search ”?q=FIND+{*TEXT*}+IN+ALL+FIELDS+RETURNING+Account+LIMIT+1”
{ "searchRecords": [ { "attributes": { "type": "Account", "url": "/services/data/v49.0/sobjects/Account/AAAAr00312rntfgAAA" }, "Id": "AAAAr00312rntfgAAA" } ] }
UI API
In a similar way as our DX API, Salesforce User Interface API allows you to fetch information from UI elements. This includes all information necessary to display a record in another application.
URIs
-
Objects:
https://MyDomain.my.salesforce.com/services/data/v49.0/ui-api/object-info/
Returns a list of all existing objects in Salesforce.
{ "objects": { "Account": { "apiName": "Account", "keyPrefix": "001", "label": "Account", "labelPlural": "Accounts", "nameFields": [ "Name" ], "objectInfoUrl": "/services/data/v49.0/ui-api/object-info/Account" },…
- Object Info:
https://MyDomain.my.salesforce.com/services/data/v49.0/ui-api/object-info/Object
Returns information for the given object. Fields, relationships…
{ "apiName": "Account", "childRelationships": [ { "childObjectApiName": "Account", "fieldName": "ParentId", "junctionIdListNames": [], "junctionReferenceTo": [], "relationshipName": "ChildAccounts" },…
- Record Info:
https://MyDomain.my.salesforce.com/services/data/v49.0/ui-api/record-ui/Id
Returns all necessary information to display an individual instance. Thus returns both UI information (formats, dropdown values…) and instance data.
{ "eTag": "bed28f6e186d8dcd4fb8ae389d74e052", "layoutUserStates": { "12t0N12345XSGBCRB3": { "id": "12t0N12345XSGBCRB3", "sectionUserStates": { "01B0N00000CtD9NUAV": { "collapsed": false, "id": "12t0N12345XSGBCRB3" }, "01B0N00000CtD9OUAV": { "collapsed": false, "id": "12t0N12345XSGBCRB3" },…
Picklist Recovery
It is a possible use case that we need to display a dropdown inside Pega with values that are configured in Salesforce, for example, a country list. It is possible to have a static copy inside a Data Type in Pega, and have a manual process to update. In case those values are not likely to be changed frequently, it could have sense. But in the case the dropdown needs to be in line, it is possible to fetch values from Salesforce by using the UI API picklist-values resource.
URI: /ui-api/object-info/{objectApiName}/picklist-values/{recordTypeId}/{fieldApiName}
{objectApiName}: Corresponds to the object name, i.e. Account.
{recordTypeId}: Corresponds to the object Salesforce ID.
{fieldApiName}: Corresponds to a field that is sourced with the picklist values we need.
To obtain the recordTypeId we can use UI API as well.
By using URL: /services/data/v49.0/ui-api/layout/{objectApiName}
This URL returns JSON which contains recrdTypeId field. For instance, for Account object it returns:
{ "eTag": "97d7a4ba47f787fa6fcd7d464210f7a6", "id": "12t0N12345XSGBCRB3", "layoutType": "Full", "mode": "View", "objectApiName": "Account", "recordTypeId": "012000000000000AAA", "sections": […
With the record type ID we can then query dropdown values for a given field, for example, if we want to recover the country codes we could use BillingCountryCode from the Account object:
/services/data/v49.0/ui-api/object-info/Account/picklist-values/012000000000000AAA/BillingCountryCode
Response:
{ "controllerValues": {}, "defaultValue": null, "eTag": "28511895e1eb8ec26640cef8816762bf", "url": "/services/data/v49.0/ui-api/object-info/Account/picklist-values/012000000000000AAA/BillingCountryCode", "values": [ { "attributes": null, "label": "Afghanistan", "validFor": [], "value": "AF" }, { "attributes": null, "label": "Aland Islands", "validFor": [], "value": "AX" },…
Examples
Accounts
When working with Salesforce, it is likely that a project requires to use SalesForce accounts. In order to fetch accounts, a Data Page can be created, sourced with a connector. Depending on the requirements (search or get Account information) we can use different resources.
- Get Account Information.
- Resource: Objects
- Connector Parameters: AccountID
- URI: sobjects/Account/{AccountID}
- Get Account Information filtered by owner.
- Resource: Query
- Connector Parameters: q
- URI sobjects/query/?q={SOQL Query}
- Query:
SELECT id, Name, Description, ,BillingCountry, BillingCity, BillingStreet, CurrencyIsoCode, Owner.Name from Account WHERE OwnerId = ‘OwnerID’
- Search Accounts by name in 50 elements pages
- Resource: Search
- Connector Parameters: q
- URI sobjects/search/?q={SOSL Query}
- Query:
FIND {*{Search Text}*} IN ALL FIELDS RETURNING Account (id, Name, Description, BillingCountry, BillingCity, BillingStreet, CurrencyIsoCode, Owner.Name LIMIT 50 OFFSET {(page-1)*50} )
Currency
Salesforce maintains a Currency conversion object which is possible to query. To fetch an actual currency conversion table (along with all existing currencies inside Salesforce) it is possible to run a query connector with the following query:
SELECT Id, IsoCode, Name, IsCorporate, ConversionRate, DecimalPlaces FROM CurrencyType WHERE IsActive=true
Field IsCorporate is true for a single record, being then considered the default currency for the entire system. Also, this currency record is used as reference for the conversion rate. This means, Conversion Rate is the relation between the record currency and the corporate currency. To explain that, here are some examples.
IsoCode | IsCorporate | Conversion Rate |
EUR | true | 1.0 |
USD | false | 1.12 |
GBP | false | 0.87 |
2 EUR to USD: Amount multiplied by To Conversion Rate = 2USD * 1.12 = 2.24USD
2 USD to EUR: Amount divided by From Conversion Rate = 2EUR / 1.12 = 1.79EUR
2 GBP to USD: First convert to EUR, then convert to USD = (2GBP / 0.87) * 1.12 = 2.57USD
Integration Configuration Exercise
Create Salesforce test environment
Salesforce allows to create developer test instances.
URL: https://developer.salesforce.com/signup
You will be requested to enter your information. This step creates your own instance and Salesforce user credentials. On submit, on first screen you receive Email to activate your account.
On Activation account, you get your application URL and username. After first login, you can see Salesforce welcome screen.
Create Salesforce connected Application
In order to allow access to Salesforce by REST API, a connected application must be created or configured. It can be done by accessing environment setup.
On the left menu select Apps -> App Manager.
Then click on “New Connected App”.
Enter the preferred application information.
Then enable OAuth and configure it. Callback URL corresponds to your Pega instance (it is available when you run the integration wizard under Authorization section).
Select from the OAuth Scopes “Manage user data via APIs (api)”.
Create new Pega - Salesforce Integration
Start REST Integration wizard from Configure -> Integration -> Connectors -> Create REST Integration.
Enter Name and Endpoint of your Salesforce instance. In this example we query accounts by name. The URL is of “query” method and Query String “q”.
Click on Add Authentication and select New Salesforce Oauth 2.0 with Grant type Authorization code.
Enter Client Information. Client Identifier and secret can be found in Salesforce application configuration. Enter the environment setup again, in the left navigation select Apps -> App Manager, then look for your application and click View from the dropdown.
Client Identifier corresponds to Consumer Key in Salesforce. Client Secret corresponds to Consumer Secret.
To authorize click the Connect button. A pop-up screen appears in your Salesforce Application. Enter your user credentials to grant access.
Continue Wizard by clicking Next. Name the resource and click again Next to advance to the JSON configuration screen.
To configure JSON to be used as base for this integration use the example from Salesforce. Click Add a REST response.
Enter the query you want to run and click on Run button. This will run the request against your instance providing the output JSON. This output will be used to generate a data model so it has properties as you select on the query. In our example we are only using “name” from Account object.
Salesforce will return all existing accounts along with the name.
Click on submit and continue Wizard. Last screen will request Data model and Ruleset information. You can use existing classes and Rulesets or create new. Filling Data layer section will end on the wizard creating the Data- class and Data Page, in case you need to use existing data model (where you will map the integration layer with your data layer) select “Skip (I’ll do it later)”. Click Create.
Wizard will start creating all needed resources. Progress will advance until it finishes.
Data Page can be tested after wizard finishes. Open and Run it. Enter same or similar query when running. Parameters for query can be removed from the Data Page, then edit Request Data Transform to setup the Query.
References
Salesforce Data Model
Salesforce REST API
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_what_is_rest_api.htm
OAuth 2.0 Authorization
Objects
Recently Viewed
SOQL Query
https://developer.salesforce.com/docs/atlas.en-us.234.0.api_rest.meta/api_rest/dome_query.htm
SOSL Search
https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_sosl.htm
SOQL and SOSL
https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm
UI API
https://developer.salesforce.com/docs/atlas.en-us.uiapi.meta/uiapi/ui_api_quick_start.htm
Get Picklist Values
Recommendations and limitations
- Use search resource instead of Query for text search (like)
- Search text is limited to a minimum of 2 characters
- Both Query and Search require specifying the list of fields to recover, not possible to use WildCard. This requires knowing in advance the available field list and specify on query/search.
- No complex Queries possible. Only possible using Alias when objects are related.
- Picklist recovery is tricky, not possible to directly link to a list, needs to use a field.