Tips and FAQ

Troubleshooting 401 Errors

Salesforce returns 401 errors when a Salesforce Sales Cloud session expires. Expired sessions are commonly caused by the following:

  • The user revoked access rights.
  • The session expired. Access tokens have a limited lifetime specified by the session timeout in Salesforce.
  • The instance is using the Username-Password OAuth Authentication method which does not allow the use of refresh tokens. For sessions that don’t expire, you may wish to switch to token based authentication for your instances.
  • Too many uses of the same credentials to authenticate. Currently, Salesforce has a limit of 5 concurrent sessions. A sixth session could invalidate a previous instance.

The most common solution is to re-authenticate the instance. If the expired instance belongs to your customer, they will be prompted to enter their credentials the next time they attempt to use the element. 

To re-authenticate via the user interface:

  1. Navigate the instance.
  2. Hover over your instance and click “Edit”.
  3. In the lower-right corner of the next page, click “RE-AUTHENTICATE” which will allow you to re-authenticate your instance using the Salesforce login page.

 To re-authenticate using the API:

  1. Navigate to your instance's custom OAuth url (this is found by making a GET request to https://api.cloud-elements.com/elements/api-v2/elements/23/oauth/url?apiKey={yourApiKey}&apiSecret={yourApiSecret}&callbackUrl={yourCallbackUrl})
  2.  Enter your Salesforce login credentials. You should then receive a new code which can be used to re-authenticate your instance.

For more information regarding the OAuth process for Salesforce Sales Cloud, see the documentation here.

How Can You Test Revoking a Salesforce OAuth Token and Re-Authenticating Your Instances Through API?

In this article, we will discuss how, if you are setting up a framework to re-authenticate instances of Salesforce Sales Cloud (SFDC), you can know how you can test that your process was successful. We will look into how to revoke an SFDC OAuth token and we will also go over a scenario that you can run through to test and ensure that your re-authentication process through API call is successful.

1. The first step is to access your SFDC account and create an OAuth/Connected App that has scopes of both 'full' and 'refresh_token, offline_access'. It is also important to pay attention to the 'Refresh Token Policy' that you set on your Connect App because that can impact your ability to re-authenticate with this described process as well.


2. Next authenticate an instance through API. The required calls and payloads are already discussed in the developer docs.


3. Access your Cloud Elements account, locate your new SFDC instance, and copy the auth header (user/org/element tokens) from the instance. For instance you can copy the full Authorization header from any endpoint after selecting your instance.

4. Now revoke the user's OAuth token either through the SFDC interface or through an API call to SFDC directly.

5. a) Revoke through the SFDC website by accessing: Setup -> Manage Apps -> Connected Apps OAuth Usage -> User Count.

Then simply click the 'Revoke' option for the desired user token you want to revoke.

5. b) Or you can use Postman or another tool to make an API call to GET /instances with your full Cloud Elements auth header including the element token, and retrieve the current oauth.user.token value.

Then make a POST to this URL to revoke the OAuth token for this instance. The Bearer in this case is equivalent to your user's OAuth token. 

- https://{SFDC-Instance}.salesforce.com/services/oauth2/revoke?token=#####

- https://help.salesforce.com/articleView?id=remoteaccess_revoke_token.htm&type=5



7. Confirm that the SFDC instance is no longer authenticated.

8. Make an API call to GET /oauth/url just as you did when you initially provisioned your instance of SFDC.

9. Access the OAuth URL generated, login to SFDC, and retrieve the provider code.

10. Make an API call to PATCH /instances with the full Cloud Elements auth header retrieved previously, blank oauth.user.refresh_token and oauth.user.token values, and the providerData.code value in the body.

11. Confirm a successful response, and verify that the SFDC instance was successfully re-authenticated.

If you are interested in seeing this process demo'ed through a quick video you can find that here:

Note that there can also be scenarios where re-authentication through API must be made via a PUT /instances containing the full instance configuration as opposed to a PATCH /instances. This can be necessary if the token has expired or if the OAuth token is revoked through alternate means than what was discussed in this article.

SOQL API

There is an undocumented API on the Salesforce Sales Cloud element that lets you pass an SOQL query directly to Salesforce. CEQL (Cloud Elements Query Language) supports, for the most part, the most basic functionality of SQL. Typically something like this:

select * from Account where Name = 'TestAccount'

Salesforce actually supports much more than this. Such as aggregate functions like count(Id) and even INNER JOIN and OUTER JOIN.

See this documentation for what salesforce supports: https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm

On Cloud Elements, you can use this extra querying functionality through the GET /query api.
The syntax is as follows:

GET /query?q=SELECT count(Id) FROM Contact WHERE name = 'test'&page=1&pageSize=200

GET /query?q=SELECT Amount, Id, Name, (SELECT Quantity, ListPrice, PricebookEntry.UnitPrice, PricebookEntry.Name FROM OpportunityLineItems) FROM Opportunity

This API is undocumented because, you will not be able to easily use a transformation on the data that comes back, and this api will not be standardized to the hub. In other words, this will only ever work for Salesforce.

Using Virtual Data Resources with Polling

You have created your virtual data resource and followed all the instructions given in our Salesforce Sales Cloud - Events / Polling and Why Would a Polling Job Fail to Return Events and still, somehow the polling for Salesforce Sales Cloud using virtual data resources is not working. Rest assured that we have seen this issue before, and we will show here all the steps you need to take in order to make sure you overcome this setback.

When you create a new instance of Salesforce with a polling configuration, one of the required fields is "Object to Monitor for Changes", essentially that is the object that we will be monitoring when a record for that Object is created, updated or deleted (i.e. Contacts, Accounts, etc...). What you may not see right away, is that an Event Poller URL is automatically generated after the instance is created and an"Object to Monitor for Changes" is provided, and this URL requires that the virtual data resource yield to some key properties in order for it to work properly with our polling engine. Here is what the Event Poller URL looks like - you can check that out by going into the instance of Salesforce Sales Cloud you have created, and scrolling down to Event Poller URL.

 

EventPollerURL.png

So let us give you a little bit more background on why the Event Poller URL is important and relevant here:

1. It sets the default value of the yielding property, in the case of Salesforce Sales Cloud, the "LastModifiedDate" property.

2. It requires deleted records to be included, hence the need to yield to the "IsDeleted" property.

3. And last, but just as important, it requires the created property to be included, so Salesforce recognizes a newly created record. 

But enough said, here are the three required properties when creating a virtual data resource and using it for polling within the Salesforce Sales Cloud element:

- "CreatedDate"

- "LastModifiedDate"

- "isDeleted"

Once you have those 3 properties mapped within your virtual data resource as well as all the other properties you would like to have included, you should be able to use the virtual data resource in the polling configuration of your Salesforce Sales Cloud element.

Maximum URL Length

Salesforce allows for a large number of custom fields. However, they have a maximum URL length when calling their API. The Salesforce element, by default queries against all available fields in each object. For example, when calling the standard GET /contacts URL the element, by default, queries against all available (standard and custom) fields in the contacts object. This can lead to the URL becoming quite long and reach the limit for the request URL. If your response URL is longer than 16,088 characters, you will get a 'Request Header Fields Too Large  StatusCode=431'. If it reaches 16,410 characters, you will get 'URI Too Long  StatusCode=414'.

If you have a large number of custom fields, you should use the GET /query resource and narrow down which fields are being returned.. For example:

GET /query?q=select%20<Attribute>%20from%20<table>%20where%20<attribute>%3D%27<search_term>%27

Steps to Re-Authenticate a SalesForce instance with the API

As you may already know, you can re-authenticate Salesforce from Cloud Elements 2.0. However, you can also do this programmatically through API calls. Follow the steps below. 

  1. Make a GET request to /elements/sfdc/oauth/url.
    curl -X GET \	
    'https://api.cloud-elements.com/elements/api-v2/elements/sfdc/oauth/url?apiKey=<your_api_key>&apiSecret=<your_api_secret>&callbackUrl=<your_callback_url>'
  2. Get the token from the OAuth 2.0 flow.
  3. Get the current instance configuration.
    curl -X GET \
    https://api.cloud-elements.com/elements/api-v2/instances/<instance_id> \
    -H 'Authorization: User <Your_user_secret>, Organization <Your_organization_secret>' \
    -H 'accept: application/json'
  4. Get the body of the response from step 3.
  5. Replace the token from step 3 with the new token from 2.
  6. PUT https://api.cloud-elements.com/elements/api-v2/api-v2/instances/{instanceId}?reAuthenticate=truewith the body being the body from the response in step 4.
  7. Make sure that in Step 6 you pass the correct authorization headers and OAuth token.

What causes the "API_DISABLED_FOR_ORG - The REST API is not enabled for this organization" error in Salesforce?

This error means that the Edition of Salesforce you are trying to connect to does not have access to the API. There are multiple editions of Salesforce, the group edition for example does not have access to the API. For more information on the available editions, please see Salesforce Documentation.

How do I attach a file to an opportunity in Salesforce using the CE API?

To do this, use the POST /{objectName}/{objectId}/attachments API where the objectName would be Opportunity and the objectID would be the ID of the opportunity you would like to attach it to. To retrieve the attachments related to an opportunity you can use the GET /{objectName}/{objectId}/attachments API.

How can I create a Salesforce CRM Instance by passing the token directly?

Via our POST /instances endpoint. See the following example payload:

{
"element": {
  "key": "sfdc"
   },
  "configuration": {
    "oauth.api.key": "<Insert_Client_ID>",
    "oauth.api.secret": "<Insert_Client_Secret>",
    "oauth.user.refresh_token": "<Insert_Refresh_Token"
   },
  "tags": [
    "<Tags>"
   ],
  "name": "PassTokenTest",
  "externalAuthentication": "initial"
}

Does GET /objects return all available objects in SFDC?

Currently, theGET /objects endpoint returns only the objects that the authenticated user has Read/Write permissions for.

Querying Numeric Fields

When querying for numeric field values in Salesforce Sales Cloud there is an important aspect of the vendor functionality to keep in mind. If you attempt to query for a field value that is technically larger than type integer can store then you will receive an error "For input string" and no records are returned.

The reason for this error is that in Salesforce queries an integer cannot be bigger than 2^31-1 (2,147,483,647); Salesforce queries (SOQL) interpret field values up to 2^31-1 as 'numbers', but values from 2^31 and greater are regarded as strings. This is an aspect of Salesforce query functionality, but fortunately there is a workaround that you can use. To get Salesforce to accept your query for these large field values you must append .0 to the end of the value, which defines the value as type decimal, which can be up to 2^63-1, and your query will be interpreted by SOQL as a number instead of a string.

For example: When querying numeric field values in a SFDC endpoint you should use a query such as `where customField__TicketID__c=7010965773.0` when the field value is greater than 2^31-1.

Is there an implementation of the Salesforce Query?

Cloud Elements offers the endpoint GET /query for the Salesforce Sales Cloud (SFDC) element only. Note that this endpoint is non-standard so it is not available in the Swagger / API Docs, but it is available on the element. Here is an example:

/hubs/crm/query?q%3Dselect%20*%20from%20opportunity


The SFDC element also supports a raw query endpoint (GET /raw-query) that can be used when nested select statements are required. Just as with /query this endpoint is not in the API Docs, but is accessible when you make API calls against SFDC element instances. An example of using this endpoint is:

/hubs/crm/raw-query?q=select%20id%20from%20Account%20where%20OwnerId%20in%20(select%20User.Id%20from%20User%20where%20User.Id%20=%20'005f4111002Nmt1XXX')

Is it possible to create custom objects for Salesforce via Cloud Elements?

Unfortunately, our API does not currently support the creation of custom objects in Salesforce Sales Cloud. 

How can I ensure that the oauth flow redirects to my sandbox for Salesforce?

You can add a siteAddress parameter to the GET /sfdc/oauth/url. For example:

https://api.cloud-elements.com/elements/api-v2/elements/sfdc/oauth/url?apiKey=<key>&apiSecret=<secret>&callbackUrl=https://console.cloud-elements.com/elements/jsp/home.jsp&siteAddress=https://test.salesforce.com>

How to post to cases in Salesforce?

You should be able to useGET /{objectName}and POST /{objectName} to access the case objects in Salesforce Sales Cloud.

How do I connect to a Salesforce Sandbox/Test User account?

Set https://test.salesforce.com as your callback/base url when setting up a new instance.

Custom Objects in Salesforce Sales Cloud

We support your custom objects and fields in the Salesforce Sales Cloud element. Use the following endpoints:

  • GET /objects to return all custom objects.
  • GET /{objectName} to interact with the custom APIs.
  • GET /objects/{objectName}/metadata endpoint to expose metadata for fields associated with your custom object.

Only Mapped Fields are Returned in Transformations

When using transformations with Salesforce Sales Cloud, only the mapped fields are returned. Salesforce requires all fields that need to be returned to be included in the request. To avoid issues with accounts that have a large number of custom fields, the transformation functionality is designed to only request the mapped fields. If a field needs to be included, or custom javascript needs to be written for a certain field, be sure to include it within your mapped fields.

What Causes Invalid Session ID Messages?

There is a setting in Salesforce that may lead to issues where calls return “INVALID_SESSION_ID – Session expired or invalid”. If this is occurring, clear the the Session Setting Lock sessions to the IP address from which they originated check box.

Accounts and Permissions

If you have different levels of permissions configured for users within your Salesforce application, those permissions will be inherited and remain unchanged through the OAuth flow as the Salesforce Sales Cloud element is integrated.

Salesforce has multiple types of accounts and editions. Only these allow you to use the API:

  • Enterprise Edition
  • Unlimited Edition
  • Developer Edition
  • Performance Edition

Visit https://help.salesforce.com/HTViewSolution?id=000005140&language=en_US for more information.

Salesforce Sandbox Environment

The Salesforce sandbox environment has a different base URL from the production environment. Instead of https://login.salesforce.com/, you log in to https://test.salesforce.com/. When you authenticate a Salesforce instance, you must pass a siteAddress query parameter with the sandbox URL when getting the redirect URL. See Authenticate Through API.

Pagination

Salesforce allows paging only up to 2000 records. If you need to go above 2000 records, you should use the orderBy function and select a unique parameter such as “Id ascending”. However the recommended approach is to use the bulk APIs

API Versions

After you connect an instance to Salesforce, Cloud Elements remains up-to-date with the latest versions of REST APIs.