Getting a List of Pardot Business Units For Your App – Programmatically

As our Pardot integrations are coping and adjusting to using the Pardot API with Salesforce SSO users, one of the new requirements is to provide the Pardot Business Unit ID in each API request. It is easy for Salesforce Administrators to get the ID, but what if we could do this with code? 

Right now, most Apps are directing Salesforce Administrators to grab the Pardot Business Unit ID  by going through these simple steps:

  1. In Salesforce Lightning, Navigate to Setup
  2. Navigate to Pardot Setup Home under Platform Tools > Pardot
  3. Next, click Assign Admin

4. On this page, you will see your Business Unit Id. Note: some people might have many Business Units!

Currently, this step can leave room for configuration errors. So now that we know how to ask for a Business Unit ID, let’s look at how  we can do this with code?  Well as you might have noticed, the Business Unit ID is a Salesforce record Id, and after a little discovery we learned that the Salesforce object name is PardotTenant.

Working with PardotTenant – REST API

Disclaimer: at the time of writing, PardotTenant is not documented and the Metadata Coverage Report shows basically nothing is supported.

That’s ok, as developers we are used to wanting documentation right! So let’s use Salesforce’s standard functionality to learn as much as we can.  For this exploring, we will be using the Workbench: REST Explorer.

Once you are logged in, we will use a GET request with the following path: /services/data/v50.0/sobjects/PardotTenant/describe

Here’s a breakdown of what we think the key fields are and what we can use:

  • Id: The Business Unit Id that is used for the API
  • PardotTenantName: The Business Unit Name that we see beside the ID in Setup.
  • PardotTenantAccountType: We’ve seen Production and Demo as values, could be used to determine which Pardot URL to use for the API
  • PardotTenantId: The Pardot Account ID that you see in Account Information in Pardot’s Settings page.

Now that we know what the fields are and what may be of use to us (for the application we are working on right?), we can use a new REST call to get the list of PardotTenants with the following path:

/services/data/v50.0/query?q=SELECT+Id,+PardotTenantName,+PardotTenantAccountType,+PardotTenantId+FROM+PardotTenant

Great, we know what REST calls need to be made and the format of the response. The tricky part is getting our Connected App to be correctly configured to enable us to get the information we need.

There are 2 key things that you need to be able to use the Salesforce REST API and get a list of Pardot Business Units.

  1. A Connected App which includes the API scope.
  2. A Salesforce User with at least a Platform license.

Needing at least a platform license is where things can get tricky.  Normally for working with the Pardot API, a User with the Identity License (along with the Connected App) is good enough.  Identity Licenses don’t provide access to most of the Pardot objects, PardotTenant included.

Troubleshooting REST Errors

This is pretty tricky, and even just writing this post I came across a few errors.

Session is not valid

[{"message": "This session is not valid for use with the REST API", "errorCode": "INVALID_SESSION_ID"}]

You will get this error if your Connected App is missing the API scope, even if your Salesforce User can see the PardotTenant object.  Simply edit your Connected App, add the API scope, wait a few minutes and then try again.

Invalid Type or The Requested Resource Does Not Exist

There could be 2 causes for you getting one of these 2 errors.

The first is that the Salesforce Org you are connecting to just might not have Pardot setup. Pretty easy to check why.

The next (that I’m not 100% sure why yet) seems to be when I used an Access Token that I received from a Username/Password Oauth authentication request, but when I issued a JWT Bearer flow authentication request this worked fine.  For production-level code, it’s best to not use Username/Password flows anyways, but during experimentation this might cause a small issue.

Working with PardotTenant – APEX

This is pretty simple, we can use a plain old SOQL statement to retrieve the information we need.

List<PardotTenant> pardotTenants = [
        SELECT Id, PardotTenantName, PardotTenantAccountType, PardotTenantId
        FROM PardotTenant
        WHERE IsDeleted = false];

However, if you are working on a Managed Package, you might get a lot of packaging complaints about PardotTenant not being available to you. In that case, you can do something a little more dynamic:

public List<PardotTenantDto> getBusinessUnits() {
        List<sObject> pardotTenants = Database.query(
                'SELECT Id, PardotTenantName FROM PardotTenant WHERE IsDeleted = false');

        List<PardotTenantDto> businessUnits = new List<PardotTenantDto>();
        for(sObject pardotTenant : pardotTenants) {
            businessUnits.add(new PardotTenantDto(
                    (String)pardotTenant.get('Id'),
                    (String)pardotTenant.get('PardotTenantName')
            ));
        }
        return businessUnits;
    }

Conclusion

Depending on your app, it might provide a better user experience to allow users setting up their Pardot connection to select from a list of Pardot Business Units, in order to help reduce the chance of configuration errors. Exploring the PardotTenant object might be a great way to get you to being able to do this. Have questions or need help exploring if this is the right path for your app? We would love to help. Reach out or shoot a question in the comments.

Published by

Adam Erstelle

Adam Erstelle is the VP of Engineering, Labs with Sercante. He loves learning about and solving really interesting challenges with Pardot and Salesforce often by building some cool tools.

Leave a Reply