With Spring ’22 released, many new features are now available in the Pardot API. From new objects to new capabilities, this blog post will highlight how to use them. Be sure to check out the Salesforce Developer Documentation for Pardot API for more information.

One of the biggest changes is that a lot more objects have been added to the Pardot API. This allows for writing more diverse integrations in an easier manner. Below is the list of new objects added in Spring ‘22. This brings the total number of objects in Pardot API v5 to 30!

  • Dynamic Content
  • Dynamic Content Variation
  • Email
  • Email Template
  • External Activity
  • Form Handler
  • Form Handler Field
  • Landing Page
  • Lifecycle Stage
  • List Email
  • List Membership
  • Opportunity
  • Prospect
  • Visitor

Continue reading to see an example of some of the new capabilities.

Assigning prospects to a list

List management endpoints have been added to Pardot API v5, which allows for retrieving prospects related to a list, adding a prospect to a list, or removing the prospect from a list.

The examples below illustrate the endpoint usage using Python 3, however the Pardot API uses RESTful HTTP methods which can be used by any programming language or utility, like Postman or cURL. In order to follow along with the examples, the Python Requests library will need to be installed; see the Requests website on installation and usage.

The Pardot API uses Salesforce OAuth for authentication, and these examples assume that Salesforce OAuth, including a Connected App, is already set up. See the Authentication Guide within the Pardot API documentation for instructions on how to set up authentication.

The goal for this example is to add all prospects with a given email address to a list with a given name. In order to make this work, we’ send a request to the Prospect Query endpoint and the List Query endpoint to find the IDs associated with the email and name. We then send a request to the List Membership Query endpoint to see if the prospect already exists on the list. If the prospect is not on the list, we send a request to the List Membership Create endpoint to add the prospect to the list.

First, we need to set up some global variables about our Salesforce Connected App and user, so that we can authenticate. The helper function get_access_token calls Salesforce OAuth to retrieve the access token. Make sure to update the global variables with the values for your account and organization.

import requests
import json

pardot_host = 'pi.demo.pardot.com'
clientId = '3MVG9My4SLBrZj220D3wrrRZXdCLWFFSWrK32_qK3fkeMLiJmS8hQiBS9L'
clientSecret = '5F419BF9EE64DBC7CB3E95966EDC1E548604D9CD51E4E36ED6C039'
username = 'email@email.com'
password = 'secret'
businessUnitId = '0UvB0000008i6XGIAY'

# Authenticate with Salesforce OAuth and retrieve an access token
def get_access_token():
    authData = {
        'grant_type': 'password',
        'client_id': clientId,
        'client_secret': clientSecret,
        'username': username,
        'password': password
    }
    r = requests.post('https://login.salesforce.com/services/oauth2/token', data=authData)
    body = r.json()
    access_token = body['access_token']
    return access_token

Once we have an access token, we can then start using the Pardot API to find the ID of the prospect, which will be used later to find and create the list membership. Depending on the Pardot account settings, there may be one, many, or no prospects with the given email address, so this code uses an array to store prospect IDs.

def find_prospects_by_email(access_token, email):
    prospect_ids = []
    next_page_token = ''

    while next_page_token is not None:
        params = { 'fields': 'id,email' }
        if len(next_page_token) > 0:
            params['nextPageToken'] = next_page_token
        headers = {
            'Authorization': 'Bearer ' + access_token,
            'Pardot-Business-Unit-Id': businessUnitId
        }
        r = requests.get(f"https://{pardot_host}/api/v5/objects/prospects", params=params, headers=headers)
        if r.status_code != 200:
            print('Failed to retrieve prospects ' + str(r.status_code) + '\n' + str(r.content))
            quit(1)
        body = r.json()
        for prospect in body['values']:
            if prospect['email'] == email:
                prospect_ids.append(prospect['id'])
        next_page_token = body['nextPageToken']
    
    if len(prospect_ids) == 0:
        print('Failed to find prospect with email ' + str(email))
        quit(2)
    return prospect_ids

Notice that this code uses the nextPageToken parameter, a new feature in the Pardot API v5 which simplifies the process of retrieving more than one page of data. The nextPageToken is faster than using offset since the page token stores information that is used on the servers to find the correct records quickly.

Now that we have the prospect IDs, we need to find the ID of List. This code also uses the nextPageParameter to efficiently page through the lists to find one with the given name. All of the new objects in Pardot API v5 offer the nextPageParameter!

def find_list_id_by_name(access_token, name):
    next_page_token = ''

    while next_page_token is not None:
        params = { 'fields': 'id,name,isDynamic' }
        if len(next_page_token) > 0:
            params['nextPageToken'] = next_page_token
        headers = {
            'Authorization': 'Bearer ' + access_token,
            'Pardot-Business-Unit-Id': businessUnitId
        }
        r = requests.get(f"https://{pardot_host}/api/v5/objects/lists", params=params, headers=headers)
        if r.status_code != 200:
            print('Failed to retrieve lists ' + str(r.status_code) + '\n' + str(r.content))
            quit(1)
        body = r.json()
        for list in body['values']:
            if list['name'] == name:
                if list['isDynamic']:
                    print('Unable to add members to a dynamic list')
                    quit(3)
                return list['id']
        next_page_token = body['nextPageToken']
    
    print('Failed to find list with name ' + str(name))
    quit(2)

The ID of the prospect and the ID of the list can be used to determine if the prospect has a list membership. Similar to the code above, we will use the query endpoint on List Membership to determine if the prospect is already assigned to the list.

def find_list_membership_by_list_and_prospect(access_token, list_id, prospect_id):
    next_page_token = ''

    while next_page_token is not None:
        params = {
            'fields': 'id,prospectId',
            'listId': list_id
        }
        if len(next_page_token) > 0:
            params['nextPageToken'] = next_page_token
        headers = {
            'Authorization': 'Bearer ' + access_token,
            'Pardot-Business-Unit-Id': businessUnitId
        }
        r = requests.get(f"https://{pardot_host}/api/v5/objects/list-memberships", params=params, headers=headers)
        if r.status_code != 200:
            print('Failed to retrieve list-memberships ' + str(r.status_code) + '\n' + str(r.content))
            quit(1)
        body = r.json()
        for list_membership in body['values']:
            if list_membership['prospectId'] == prospect_id:
                return list_membership['id']
        next_page_token = body['nextPageToken']
    
    return None

To finish out the task of adding the prospect to the list, we can tie all of the above functions together to create the list membership if it is not found.

def create_list_membership(access_token, list_id, prospect_id):
    params = {'fields': 'id'}
    data = {
        'prospectId': prospect_id,
        'listId': list_id
    }
    headers = {
        'Authorization': 'Bearer ' + access_token,
        'Pardot-Business-Unit-Id': businessUnitId
    }
    r = requests.post(f"https://{pardot_host}/api/v5/objects/list-memberships", params=params, json=data, headers=headers)
    if r.status_code != 201:
        print('Failed to create list membership ' + str(r.status_code) + '\n' + str(r.content))
        quit(1)
    body = r.json()
    return body['id']

access_token = get_access_token()
prospect_ids = find_prospects_by_email(access_token, 'codey@salesforce.com')
list_id = find_list_id_by_name(access_token, 'Trailblazers')
for prospect_id in prospect_ids:
    list_membership_id = find_list_membership_by_list_and_prospect(access_token, list_id, prospect_id)
    if list_membership_id is not None:
        print('List membership already exists for prospect ' + str(prospect_id))
    else:
        list_membership_id = create_list_membership(access_token, list_id, prospect_id)
        print('Created new list membership prospect ' + str(prospect_id) + ': ' + str(list_membership_id))

When we run this code, all of the prospects associated with the email “codey@salesforce.com” will be assigned to the “Trailblazers” list. If no prospects are found, or the list doesn’t exist, an error is returned.

Conclusion

With Spring ’22 generally available, many new objects and capabilities are now available in the Pardot API. The examples above demonstrate the ease in which data can be retrieved and processed using the new endpoints in the Pardot API. Make sure to checkout the Salesforce Developer Documentation for Pardot API to see other great things that can be achieved with the Pardot API.

About the author

Jared Pearson is an engineer at Salesforce. He’s been helping customers use Salesforce technologies to build cool features for over 10 years.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS