# developer Account Engagement API (pardot) - Full Documentation # Account Engagement API Quick Start This tutorial walks you through a few real-life tasks so you can start automating and extending Account Engagement. In this guide, we implement authentication by using an OAuth2.0 flow, and then make some example calls and complete a basic task. Before you begin, make sure that you have: - A Salesforce admin to create an external client app and gather information. - A Salesforce user with single sign-on (SSO) enabled for Account Engagement. - A configured Account Engagement business unit. - Selected which OAuth flow works best for your case. This tutorial uses the Web Server OAuth flow. This tutorial requires knowledge of external client apps and authentication. If you aren't familiar with these topics, review the concepts in [External Client Apps](https://help.salesforce.com/s/articleView?id=xcloud.external_client_apps.htm) first. After you familiarize yourself with the basics, come back to this tutorial. **warning:** The calls you make during this tutorial have the potential to impact both your Salesforce and Account Engagement settings and data. If you’re just testing the API, make sure that you’re using a sandbox account. If you’re using this tutorial to set up your production account, use caution. ## Authentication To authenticate Account Engagement API requests, you must use an SSO-enabled Salesforce user who has Account Engagement access and an OAuth flow with an external client app. ### Step 1: Create the External Client App in Salesforce The first step in authentication is creating an external client app. An external client app is a framework that enables an external app to integrate with Salesforce by using APIs and standard protocols like OAuth. External client apps use these protocols to authenticate, authorize, and provide SSO for external apps. To put it simply, an external client app represents an integration. See [External Client Apps](https://help.salesforce.com/s/articleView?id=xcloud.external_client_apps.htm&type=5). To set up an external client app, have a Salesforce admin follow these steps: 1. From Salesforce Setup, in the Quick Find box, enter **External Client Apps**, and then select **External Client Manager**. 2. Click **New External Client App**. 3. Configure the external client app. 1. Name the external client app. 2. Add the email address for the admin who manages Agentforce. 3. From the Distribution State picklist, select **Local**. 4. In the API section, select **Enable OAuth Settings**. 5. Enter a callback URL. The callback URL is used to redirect users after authentication in browser-based flows. This example uses `https://my.example.com/myapp`. If you use a browser-based flow, such as Web Server Flow or User Agent Flow, the URL must match the URL you pass as a callback to OAuth endpoints. If you aren’t using a browser-based flow, the URL isn’t used. 6. To give the app access to Account Engagement, under **Selected OAuth Scopes**, add **Manage Pardot services**. For more complex scenarios, such as using refresh tokens, select other scopes as well. 4. Click **Create**. **note:** The external client app requires up to 15 minutes before it's available for authentication. ### Step 2: Gather Important Information Now that you have an external client app, gather some important information you need handy to finish setting up authentication. The primary details are: - External Client App Consumer Key: a unique identifier for your external client app. - External Client App Consumer Secret: a password for the external client app. - Business Unit IDs: Because a Salesforce org can have multiple business units, the ID routes the API request to the correct business unit. You need the ID even if you have only one business unit. - Salesforce User: A Salesforce user with SSO enabled for Account Engagement. Because all of this information is sensitive, carefully consider how to share these details with other team members securely. #### Find the Consumer Key and Secret 1. From Salesforce Setup, in the Quick Find box, enter **External Client**, and then select **External Client Manager**. 2. Go to your external client app and select **Settings**. 3. In the OAuth settings, click **Consumer Key and Secret**. 4. Copy your consumer key. 5. Reveal and copy your consumer secret. #### Find the Account Engagement Business Unit IDs 1. From Marketing Setup, in the Quick Find box, enter **Pardot**, and then select **Pardot Account Setup**. 2. Copy the business unit ID for the Account Engagement instance you want to use. #### Choose the Integration User For the integration user, we recommend that you create a unique user for each specific app integration. The user must be SSO-enabled and have access to Account Engagement. ### Step 3: Implement OAuth Flow Salesforce has several OAuth flows to meet your unique security and integration needs. In this tutorial, we use the [Web Server OAuth flow](https://help.salesforce.com/articleView?id=sf.remoteaccess_oauth_web_server_flow.htm). This flow is ideal for when you don’t want to store the end user’s credentials in your system. To learn more about your options and how to choose the best OAuth flow for your integration, check out [Salesforce OAuth Help Documentation](https://help.salesforce.com/articleView?id=sf.remoteaccess_authenticate.htm). 1. Have your integration direct the user to Salesforce’s OAuth authorization endpoint: `https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https://my.example.com/myapp` - Replace `CLIENT_ID` with your external client app consumer key. - Replace `https://my.example.com/myapp` with your redirect URI. 2. If the user doesn’t have an active session, they’re prompted to log into Salesforce. 3. The user grants the app permission. 4. After the user has logged in and allowed the app, Salesforce redirects you back to the `redirect_uri` passed in to the `authorize` endpoint:`https://my.example.com/myapp?code=` 5. Your server-side code exchanges this code for an access token by making a POST request to the Salesforce OAuth token endpoint: ``` POST /services/oauth2/token HTTP/1.1 Host: login.salesforce.com Content-type: application/x-www-form-urlencoded grant_type=authorization_code& code=& client_id=& client_secret=& redirect_uri=https://my.example.com/myapp ``` 6. After Salesforce validates the external client app credentials and authorization code, the endpoint responds with an access token: ```json { "Access_token": "", "signature": "", "instance_url": "https://MyDomainName.my.salesforce.com", "id": "https://login.salesforce.com/id/00000000000/0000000000", "token_type": "Bearer", "issued_at": "1558553873237" } ``` The access token can be used to make calls to the Account Engagement API. The code was exchanged for the access token on the server side and not from the user’s browser. Because of how the code was exchanged, there’s no opportunity for malicious JavaScript to steal the access token. After you’ve implemented authorization, you can start working with the Account Engagement API. ## Working with the API With the Account Engagement API, your app can access current data within Account Engagement. Through the API, you can perform several common operations on Account Engagement objects including: - `create`: Creates an instance of the object with the specified parameters. - `read`: Retrieves information about the specified object. - `query`: Retrieves objects that match the specified criteria. - `update`: Updates elements of an existing object. - `upsert`: Updates elements of an existing object if it exists. If the object doesn’t exist, one is created using the supplied parameters. Developers must authenticate using a Salesforce OAuth endpoint or the Account Engagement API login endpoint before issuing Account Engagement API requests. Refer to the Authentication section for details about this procedure. Keep in mind a few considerations when you perform requests. For update requests, only the fields specified in the request are updated. All others are left unchanged. If a required field is cleared during an update, the request is declined. ### Request Format All requests to the API must: - Use either HTTP GET or POST. Version 5 also supports PUT and DELETE requests. - Pass the access token in an HTTP Authorization header. - Pass the Account Engagement Business Unit ID in an HTTP Pardot-Business-Unit-Id header. - Use the correct URL for your Account Engagement environment. ### Our First GET Request In this example, we want to get a list of all custom fields in a business unit. Before you begin, make sure you’ve authenticated and have a valid access token. For simplicity in this example, these calls are written in HTTP. ``` GET /api/customField/version/4/do/query?format=json HTTP/1.1 Host: pi.pardot.com Authorization: Bearer Pardot-Business-Unit-Id: ``` #### Breaking Down the Request Let’s break down the call and identify its parts, starting with the uniform resource identifier (URI). `GET https:///api//version//do/?format=` - **Environment URL**: In the example, we use pi.pardot.com, but you use the URL that matches your environment type. Demos, developer orgs, and sandbox environments are hosted on the domain pi.demo.pardot.com. Training and production environments are hosted on the domain pi.pardot.com. - **Object**: The object we’re requesting data for. In our example, we’re querying the CustomField object. - **API version**: The version of the API you’re using. Here, we use v4. - **Operation**: The operation you’re performing. Here, we use `query`. - **Format**: The output format, either XML or JSON. Here, we use `json`. Now that we’ve explained the URI, let’s examine the header lines in the call. - `Authorization: Bearer ` lets Account Engagement know that you’ve authenticated and have permission to access data. - `Pardot-Business-Unit-Id: ` lets Account Engagement know which business unit you want data from. - `Host`: The URL for your Account Engagement environment. #### Breaking Down the Response The call returns the business unit’s custom fields and their metadata. ```json { "@attributes": { "version": 1, "stat": "ok" }, "result": { "customField": [ { "id": 14141, "is_use_values": false, "crm_id": null, "is_record_multiple_responses": false, "field_id": "Attended_Event", "type_id": 1, "updated_at": "2020-08-04 05:45:36", "is_analytics_synced": false, "type": "Text", "created_at": "2020-08-04 05:45:36", "name": "Attended Event?" }, { "id": 14143, "is_use_values": false, "crm_id": null, "is_record_multiple_responses": false, "field_id": "Birthday", "type_id": 12, "is_analytics_synced": false, "updated_at": "2020-08-04 05:45:56", "created_at": "2020-08-04 05:45:56", "name": "Birthday", "type": "Date" } ], "total_results": 2 } } ``` Learn more about each object’s fields in the [Object Field Reference documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/object-field-reference.md). ### Our First POST Request **warning:** If you’re following along with your Account Engagement instance, this next example creates a list in your account. Either use a sandbox account or customize the example to fit your needs. In this example, we create a list for a spring nurturing campaign. Before you begin, make sure you’ve authenticated and have a valid access token. ``` POST /api/list/version/4/do/create?format=json HTTP/1.1 Host: pi.pardot.com Content-Type: application/x-www-form-urlencoded Authorization: Bearer Pardot-Business-Unit-Id: name=Spring Leads Nurture&title=Spring Leads title&description=A list to nurture spring leads ``` #### Breaking Down the Request We went over the URI and the authorization and business unit headers in the GET example. Let’s cover the other components: - `Content-Type: application/x-www-form-urlencoded`: Tells the server what kind of data is included in the request. - `name=Spring Leads Nurture`: Sets the internal name of the list to "Spring Leads Nurture." - `title=Spring Leads`: Titles the list "Spring Leads." - `description=A list to nurture spring leads`: Adds a text description to the list. #### Breaking Down the Response When we send this request to the server, Account Engagement responds by creating a list with the criteria that we specified. The response looks like this: ```json { "@attributes": { "stat": "ok", "version": 1 }, "list": { "id": 1000, "name": "Spring Leads Nurture", "is_public": false, "is_dynamic": false, "title": "Spring Leads", "description": "A list to nurture spring leads ", "is_crm_visible": false, "created_at": "2021-02-12 08:09:10", "updated_at": "2021-02-12 08:09:10" } } ``` ### Going Further Let’s take the example a step further and add a prospect to our new list. Remember that completing this task changes data in Account Engagement, so proceed with caution. Before you begin, make sure you’ve authorized and have a valid access token. For simplicity in this example, we make these calls in our command-line interface using cURL. First, copy the list ID for the list you want to add a prospect to. Then, find the IDs for the prospect you want to add to the list. You can use `query` on the Prospect object to get ID. - List ID: 1000 - Prospect ID: XXXXX ``` POST /api/prospect/version/4/do/update/id/XXXXX?format=json HTTP/1.1 Host: pi.pardot.com Content-Type: application/x-www-form-urlencoded Authorization: Bearer Pardot-Business-Unit-Id: list_=1000 ``` Notice that the URI includes the prospect’s ID: XXXXX. When we send this request, Account Engagement adds that prospect to the list with the ID 1000. ## What’s Next It can be helpful to talk to other developers about the problems you’re working on. Connect with like-minded Account Engagement developers by joining a [Trailblazer Community Group](https://trailblazercommunitygroups.com/) near you. ## See Also - _Salesforce Help_: [External Client Apps](https://help.salesforce.com/s/articleView?id=xcloud.external_client_apps.htm) - _Salesforce Help_: [Authorize Apps with OAuth](https://help.salesforce.com/articleView?id=sf.remoteaccess_authenticate.htm) # Account Engagement Open-Source Labs Apps The following apps are provided as-is and are managed as open-source projects. These applications provide solutions to various customer pain points for marketers. Even better, the apps provide real-world examples that developers can leverage to start their own application. Here is an overview of the apps at your disposal. | Application Name | Customer Value | AppExchange Listing | GitHub Location | Example of | | --------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | Embedded Feedback within Account Engagement Emails | Gather instant feedback from prospects within Account Engagement emails. | [Listing](https://appexchange.salesforce.com/listingDetail?listingId=a0N3u00000PGx6K) | [Repo](https://github.com/SalesforceLabs/Pardot-Embedded-Feedback) | Email builder custom component | | Account Engagement List Control For Salesforce | Easily manage your prospects without leaving your Salesforce record. | [Listing](https://appexchange.salesforce.com/listingDetail?listingId=a0N3u00000PGzZ4) | [Repo](https://github.com/SalesforceLabs/MJPardotContest) | Account Engagement API integration | | Newsletter Lightning Email Template with Google API custom components | Create a newsletter with components for YouTube, Webinars, and Google Calendar. | [Listing](https://appexchange.salesforce.com/listingDetail?listingId=a0N3u00000PH6eV) | [Repo](https://github.com/SalesforceLabs/GoogleAPIsIntegratedEmailTemplate) |
  • Packaged email template
  • Email builder custom component
| | Account Engagement Forms Everywhere! | Use your Account Engagement forms all over Salesforce. | [Listing](https://appexchange.salesforce.com/listingDetail?listingId=a0N3u00000PH6Zf) | [Repo](https://github.com/SalesforceLabs/PardotFormsEverywhere) |
  • Email builder custom component
  • Account Engagement API integration
| | Video for Email | Add video to your emails in a delightfully simple way. | [Listing](https://appexchange.salesforce.com/listingDetail?listingId=a0N3u00000PH4Io) | [Repo](https://github.com/SalesforceLabs/Video-Email) |
  • Email builder custom component
  • External API Integration
| | Email Validator for Account Engagement | Keep your prospect database clean and improve email deliverability. | [Listing](https://appexchange.salesforce.com/ListingDetail?listingId=a0N3u00000RNEwI) | [Repo](https://github.com/SalesforceLabs/EmailValidator) |
  • External Actions (Apex)
  • API V5
  • API Authentication
| Love these ideas and want to make them your own? Check out our [Account Engagement ISV Getting Started](https://developer.salesforce.com/docs/marketing/pardot/guide/isv-getting-started.html). # Additional Resources Use these resources to get the most out of the Account Engagement API. ## Trailhead - [Marketing Cloud Account Engagement API: Quick Look](https://trailhead.salesforce.com/content/learn/modules/pardot-api-quick-look): Learn how APIs can extend and automate Account Engagement for your business. - [Marketing Cloud Account Engagement Basics](https://trailhead.salesforce.com/content/learn/modules/pardot-basics-lightning): Learn what Account Engagement is and how it can help you market to other businesses. ## Postman Account Engagement has a public Postman collection for v5 of the API. Postman simplifies making calls and experimenting with the API. Learn more, and install the collection from [GitHub](https://github.com/pardot/postman-pardot-apis). If you're not familiar with Postman, check out the [Postman API Client](https://trailhead.salesforce.com/content/learn/modules/postman-api-client) module on Trailhead. ## Help Content Use [Salesforce Help](https://help.salesforce.com/s/articleView?id=sf.bundle_pardot_parent.htm&type=5) to discover more about Account Engagement features and capabilities. # API V5 for Flow Development Guide ## Introduction With API V5 for Flow, admins can manage their content and customize their management processes in powerful, new ways. Use API V5 Flow for these actions. 1. Import Content Templates 2. Connect external content builders to Account Engagement 3. Copy content and assets between business units 4. Copy assets from Sandbox to Production orgs and vice versa ## Basics of Salesforce Flow Build custom user interfaces, create custom tasks, and schedule automated workflows by using Salesforce Flow. This guide focuses on-screen flow use cases. To learn about other Salesforce Flow use cases, and to learn more about flow in general, refer to these Trailheads. 1. [Flow Trail](https://trailhead.salesforce.com/content/learn/trails/build-flows-with-flow-builder) 2. [Schedule-Triggered Flows](https://help.salesforce.com/apex/HTViewHelpDoc?id=sf.flow_considerations_trigger_schedule.htm&language=en_US) 3. [Flow Types](https://help.salesforce.com/s/articleView?id=sf.flow_concepts_type.htm&language=en_US&r=https%3A%2F%2Fwww.google.com%2F&type=5) This guide assumes you have a baseline understanding of Salesforce Flow. Flow will seem familiar to users of Engagement Studio, in that it also includes: 1. A Visual Builder Interface using a Canvas 2. Top-to-Bottom Workflow using Steps 3. Salesforce Object Triggers (Flow doesn’t have the concept of triggers within a flow) 4. Three basic concepts for screen flows: - Screens - Used to Interact with User and Gather Input - Actions - Used to Retrieve Data or Execute an Action - Conditions - Used to create criteria to determine a path Because it’s designed for general processes, Flow is more advanced than Engagement Studio. Note these capabilities. 1. Define objects 2. Add custom actions 3. Perform loops 4. Package Flows ## API V5 Flow Actions API V5 is integrated into Flow using Apex Invocable Actions, which expose the Account Engagement API to Flow. With Flow, you can perform these general functions. 1. Generate Picklists - Use: A user can search for and select a record. - Input: - Object Name - Business Unit ID - Output - JSON String of Content Name, Content Record IDs 2. Create an Asset - Use: Creates a content record. - Action Naming Schema: Create X Record - Input: - Asset ID 3. Read an Asset - Use: Retrieve all the data for an asset. - Action Naming Schema: Read X Record - Input: - Asset ID - Output: - Content Record To store the results of the Read and Create actions, each supported object needs an associated Apex Defined Object Class to represent the data in the object. ## Getting Started Checklist - Access to Salesforce org with Marketing Cloud Account Engagement - User Access to build and run Flows - User Access to relevant business units - Install the latest Marketing Cloud Account Engagement Managed Package ## API V5 for Flow Actions ### Bulk Action Endpoints **Get My Business Unit**
Retrieves the list of business units relevant to a given user. | API Object | Inputs | Outputs | Additional Details | | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | [Business Unit Context](https://developer.salesforce.com/docs/atlas.en-us.238.0.chatterapi.meta/chatterapi/connect_resources_pardot_business_unit_context.htm) | **From Sandbox (Boolean)**
Choose to query for Business Units from the Sandbox (applicable for Sandbox-Production Bulk Asset Copy Flow).Overrides the Folder

**Named Credential (String)**
Use for Salesforce Metadata API Access. | **Picklist Output (Object List)**
A list of business units names and IDs.Overrides the Folder | The results only include the business units that the active user of the flow has access to. | **Generate Flow Context**
Combine all the variables, and then generate a context that can be used as an input for all the invocable actions. | Inputs | Outputs | Additional Details | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | **Interview Guide (String)**
The value of $Flow.InterviewGuide.Overrides the Folder

**Named Credential to Use for Account Engagement API Access (String - Optional)**
API name to access cross-org Account Engagement API.Overrides the Folder

**Production Business Unit ID (String - Optional)**

**Sandbox Business Unit ID (String - Optional)**

**Copy from Production to Sandbox (Boolean - Optional)**
True when copying from Sandbox to Production org. The default value is null. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Flow Context (FlowContextModel)**
The generated Flow Context. | All the fields except the Interview Guide are only applicable when copying assets from Sandbox to Production orgs and vice versa. | **Get Dropdown Options**
Retrieves a list of options for the given object and business unit. | API Object | Inputs | Outputs | Additional Details | | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Multiple | **Business Unit ID (String)**
The ID of the business unit to access.

**Query Object (String)**
The V5 API name of the object that you want to retrieve dropdown options.

**Field Parameters (String - Optional)**
The fields to use for the name and value for the dropdown. The default is “id, name” and, for most objects, doesn’t require a change.

**Flow Context (FlowContextModel)**
Context generated using Generate Flow Context invocable action. | **Picklist Output (PickListOutput[])**
The names and values of the returned object records | The action uses the API V5 query API, so it follows any query data restrictions that exist for that object. For example, the HTML field for email templates can’t be returned in a query.

**Objects Supported:**
  • email-templates
  • custom-fields
  • custom-redirects
  • files
  • folders
  • campaigns
  • tracker-domains
  • engagement-studio-programs
  • forms
  • form-handlers
  • dynamic-content
  • landing-pages
  • layout-templates
| **Get Email Template**
Retrieves the details of an Email Template. | API Object | Inputs | Outputs | | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Email Template](https://developer.salesforce.com/docs/marketing/pardot/guide/email-template-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Email Template (Object)**
An Email Template object record. Able to pass the object returned in the Get Email Template action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Email Template (Object)**
The Email Template represented by the input ID. | **Copy Email Template**
Creates an Email Template by using the provided inputs. | API Object | Inputs | Outputs | | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Email Template](https://developer.salesforce.com/docs/marketing/pardot/guide/email-template-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Campaign ID (String - Optional)**
Overrides the Campaign to use when creating the Email Template.

**Folder ID (String - Optional)**
Overrides the Folder to use when creating the email template.

**Tracker Domain ID (String - Optional)**
Overrides the tracker domain to use when creating the email template.

**Email Template (Object)**
An email template object record. Able to pass the object returned in the Get Email Template action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Email Template (Object)**
The newly created Email Template. | **Get Custom Redirect**
Retrieves the details of a Custom Redirect. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Custom Redirect](https://developer.salesforce.com/docs/marketing/pardot/guide/custom-redirect-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Custom Redirect (String)**
The ID of the Custom Redirect that you want to retrieve.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Custom Redirect (Object)**
The Custom Redirect represented by the input ID. | **Copy Custom Redirect**
Creates a Custom Redirect by using the provided inputs. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Custom Redirect](https://developer.salesforce.com/docs/marketing/pardot/guide/custom-redirect-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Campaign ID (String)**
Overrides the Campaign to use when creating the Custom Redirect.

**Folder ID (String)**
Overrides the Folder used to use when creating the Custom Redirect.

**Tracker Domain ID (String)**
Overrides the Tracker Domain to use when creating the Custom Redirect.

**Custom Redirect (CustomRedirectModel)**
A Custom Redirect object record. Can pass the object returned in the Get Custom Redirect action as an input.

**Flow Context (FlowContextModel)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Custom Redirect (Object)**
The newly created Custom Redirect. | **Get Custom Field**
Retrieves the details of a Custom Field. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Custom Field](https://developer.salesforce.com/docs/marketing/pardot/guide/custom-field-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Custom Field ID (String)**
The ID of the Custom Field that you want to retrieve.

**Flow Context (FlowContextModel)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Custom Field (CustomFieldModel)**
The Custom Field represented by the input ID. | **Copy Custom Field**
Creates a Custom Field using the provided inputs. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Custom Redirect](https://developer.salesforce.com/docs/marketing/pardot/guide/custom-redirect-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Campaign ID (String)**
Overrides the Campaign to use when creating the Custom Redirect.

**Folder ID (String)**
Overrides the Folder used to use when creating the Custom Redirect.

**Tracker Domain ID (String)**
Overrides the Tracker Domain to use when creating the Custom Redirect.

**Custom Redirect (CustomRedirectModel)**
A Custom Redirect object record. Can pass the object returned in the Get Custom Redirect action as an input.

**Flow Context (FlowContextModel)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Custom Redirect (Object)**
The newly created Custom Field. | **Get Dynamic Content**
Retrieves the details of Dynamic Content. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Dynamic Content](https://developer.salesforce.com/docs/marketing/pardot/guide/dynamic-content-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Custom Dynamic Content ID (String)**
The ID of the Dynamic Content that you want to retrieve.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Dynamic Content(DynamicContentModel)**
The Dynamic Content represented by the input ID. | **Copy Dynamic Content**
Creates new Dynamic Content using the provided inputs. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [Dynamic Content](https://developer.salesforce.com/docs/marketing/pardot/guide/dynamic-content-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Folder ID (String)**
Overrides the Folder to use when creating the Dynamic Content.

>**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Dynamic Content (DynamicContentModel)**
The newly created Dynamic Content. | **Get Engagement Studio Program**
Retrieves the details of an Engagement Studio Program. | API Object | Inputs | Outputs | | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Engagement Studio Program](https://developer.salesforce.com/docs/marketing/pardot/guide/engagement-studio-program-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Engagement Studio Program ID (String)**
The ID of the Engagement Studio Program that you want to retrieve.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Engagement Studio Program (EngagementStudioProgramModel)**
The Engagement Studio Program represented by the input ID. | **Copy Engagement Studio Program**
Creates an Engagement Studio Program using the provided inputs. | API Object | Inputs | Outputs | | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Engagement Studio Program](https://developer.salesforce.com/docs/marketing/pardot/guide/engagement-studio-program-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Destination Business Unit ID (String)**
The ID of the business unit to access.

**Folder ID (String)**
Overrides the Folder to use when creating the Engagement Studio Program.

**Engagement Studio Program (EngagementStudioProgramModel)**
An Engagement Studio Program object record. Can pass the object returned in the Get Engagement Studio Program action as an input.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Engagement Studio Program (EngagementStudioProgramModel)**
The newly created Engagement Studio Program. | **Get File**
Retrieves the details of a File. | API Object | Inputs | Outputs | | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [File](https://developer.salesforce.com/docs/marketing/pardot/guide/file-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**File ID (String)**
The ID of the File that you want to retrieve.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**File (FileModel)**
The File represented by the input ID. | **Copy File**
Creates a File using the provided inputs. | API Object | Inputs | Outputs | | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [File](https://developer.salesforce.com/docs/marketing/pardot/guide/file-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**File ID (String)**
**Campaign ID (String - Optional)**
Overrides the Campaign to use when creating the file.

**Folder Id (String)**
Overrides the Folder to use when creating the File.

**Tracker Domain ID (String)**
Overrides the tracker domain to use when creating the File.

**File (FileModel)**
A File object record. Can pass the object returned in the Get File action as an input.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**File (FileModel)**
The newly created File. | **Get Form**
Retrieves the details of a Form. | API Object | Inputs | Outputs | | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [Form](https://developer.salesforce.com/docs/marketing/pardot/guide/form-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Form ID (String)**
The ID of the Form that you want to retrieve.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Form (FormModel)**
The Form represented by the input ID. | **Copy Form**
Creates a Form by using the provided inputs. | API Object | Inputs | Outputs | | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Form](https://developer.salesforce.com/docs/marketing/pardot/guide/form-v5.html) | **Source Business Unit ID (String)**
The ID of the business unit to access.

**Destination Business Unit ID**
The ID of the business unit to access.

**Campaign ID (String)**
Overrides the Campaign to use when creating the Form.

**Folder ID (String)**
Overrides the Folder to use when creating the Form.

**Tracker Domain ID (String)**
Overrides the tracker domain to use when creating the Form.

**Layout Template ID (String)**
Overrides layout template to use when creating the Form.

**Form (FormModel)**
A Form object record. Can pass the object returned in the Get Form action as an input.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Form (FormModel)**
The newly created Form. | **Get Form Handler**
Retrieves the details of a Form Handler. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Form Handler](https://developer.salesforce.com/docs/marketing/pardot/guide/form-handler-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Form Handler ID (String)**
The ID of the Form Handler that you want to retrieve.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Form Handler (FormHandlerModel)**
The Form Handler represented by the input ID. | **Copy Form Handler**
Creates a Form Handler using the provided inputs. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Form Handler](https://developer.salesforce.com/docs/marketing/pardot/guide/form-handler-v5.html) | **Source Business Unit ID (String)**
The ID of the business unit to access.

**Destination Business Unit ID**
The ID of the business unit to access.

**Campaign ID (String)**
Overrides the Campaign to use when creating the Form.

**Folder ID (String)**
Overrides the Folder to use when creating the Form.

**Tracker Domain ID (String)**
Overrides the tracker domain to use when creating the Form Handler.

**Form Handler (FormHandlerModel)**
A Form Handler object record. Can pass the object returned in the Get Form Handler action as an input.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Form Handler (FormHandlerModel)**
The newly created Form Handler. | **Get Layout Template**
Retrieves the details of a Layout Template. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Layout Template](https://developer.salesforce.com/docs/marketing/pardot/guide/layout-template-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Layout Template ID (String)**
The ID of the Layout Template that you want to retrieve.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Layout Template (LayoutTemplateModel)**
The Layout Template represented by the input ID. | **Copy Layout Template**
Creates a Layout Template using the provided inputs. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [Layout Template](https://developer.salesforce.com/docs/marketing/pardot/guide/layout-template-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Folder ID (String)**
Overrides the Folder to use when creating the Layout Template.

**Layout Template ID (String)**
Overrides the layout template object record. Can pass the object returned in the Get Layout Template action as an input.

**Layout Template (LayoutTemplateModel)**
A Layout Template object record. Can pass the object returned in the Get Layout Template action as an input.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Layout Template (LayoutTemplateModel)**
The newly created Layout Template. | **Get Landing Page**
Retrieves the details of a Landing Page. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Landing Page](https://developer.salesforce.com/docs/marketing/pardot/guide/landing-page-v5.html) | **Business Unit ID (String)**
The ID of the business unit to access.

**Landing Page ID (String)**
The ID of the Landing Page that you want to retrieve.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Landing Page (LandingPageModel)**
The Landing Page represented by the input ID. | **Copy Landing Page**
Creates a Landing Page using the provided inputs. | API Object | Inputs | Outputs | | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Landing Page](https://developer.salesforce.com/docs/marketing/pardot/guide/landing-page-v5.html) | **Source Business Unit ID (String)**
The ID of the business unit to access.

**Destination Business Unit ID**
The ID of the business unit to access.

**Campaign ID (String - Optional)**
Overrides the Campaign to use when creating the Landing Page.

**Folder ID (String)**
Overrides the Folder to use when creating the Landing Page.

**Folder ID (String)**
Overrides the Folder to use when creating the Landing Page.

**Tracker Domain ID (String - Optional)**
Overrides the tracker domain to use when creating the Landing Page.

**Landing Page (LandingPageModel)**
A Landing Page object record. Can pass the object returned in the Get Landing Page action as an input.

**Flow Context (FlowContextModel - Optional)**
Flow context generated using Generate Flow Context invocable action. | **Message (String)**
An action success or failure message.

**Is Success? (Boolean)**
An action success or failure indicator.

**Landing Page (LandingPageModel)**
The newly created Landing Page. | ## API V5 for Flow Lightning Web Components | LWC | Purpose | Input | Output | | ----------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | combobox | Type ahead search with multi-select/single-select option. | `label: String:`

`required: Boolean`
`multiSelect: Boolean`
whether the combobox is multi-select or not

`messageWhenInvalid: String`
Displays the given error with this message if necessary is true and the user doesn’t select the value.

`options: PicklistOutput[]` | `selectedValue: String`
Returns selected value for single-select combobox.
`selectedValues: String[]`
Returns a list of selected values for a multi-select combobox.
| | previewAssets | Preview the asset in a tabular format with given data. | `emailTemplates: EmailTemplateModel[]`

`customRedirects: CustomRedirectModel[]`
`files: FileModel[]`
`customFields: CustomFieldModel[]`
`engagementStudioPrograms: EngagementStudioProgramModel[]]`
`layoutTemplates: LayoutTemplateModel[]`
`formHandlers: FormHandlerModel[]`
`dynamicContent: DynamicContentModel[]`
`forms: FormModel[]`
`landingPages: LandingPageModel[]` | Displays the assets on the flow `screen`. | | progressIndicator | Displays progress based on provided current step. | `currentStep: Integer` | Displays the progress indicator (steps) on the flow screen. | ## API V5 for Flow Apex Defined Objects These sections detail the unique objects provided in the API V5 for Flow toolkit. ### Picklist Output The following is a general class to store picklist values for Account Engagement objects. A picklist output includes a display value that shows the user, and a reference ID to retrieve the record the user selects. ```apex PicklistOutput { String id; String name; String domain; // to support tracker-domain picklist } ``` ### Email Template The Email Template model represents an Account Engagement Email Template. ```apex EmailTemplateModel { Integer id; String name; String subject; String htmlMessage; String textMessage; Boolean isOneToOneEmail; Boolean isAutoResponderEmail; Boolean isDripEmail; Boolean isListEmail; List senderOptions; Integer trackerDomainId; Integer folderId; String type; Integer campaignId; SenderOption { String type; String address; String name; } ``` ### Custom Redirect The custom redirect model represents an Account Engagement Custom Redirect. ```apex CustomRedirectModel { Integer id; String name; String destinationUrl; Integer folderId; Integer campaignId; Integer trackerDomainId; String vanityUrlPath; String gaCampaign; String gaContent; String gaMedium; String gaSource; String gaTerm; } ``` ### Custom Field The Custom Field model represents an Account Engagement Custom Field. ```apex CustomFieldModel { String fieldId; Integer id; Boolean isRecordMultipleResponses; Boolean isRequired; Boolean isUseValues; String name; String salesforceId; String type; String statusText; String errorMessage; } ``` ### File The File model represents an Account Engagement File. ```apex FileModel { Integer id; String name; Integer folderId; Integer campaignId; Integer trackerDomainId; String url; String statusText; String errorMessage; } ``` ### Engagement Studio Program The Engagement Studio Program model represents an Account Engagement Studio Program. ```apex EngagementStudioProgramModel { Integer id; String name; Integer folderId; String statusText; String errorMessage; } ``` ### Form The Form model represents an Account Engagement Form. ```apex FormModel { Integer id; String name; Integer campaignId; Integer folderId; Integer trackerDomainId; Integer layoutTemplateId; String submitButtonText; String redirectLocation; String thankYouContent; String thankYouCode; String beforeFormContent; String afterFormContent; String fontSize; String fontFamily; String fontColor; String labelAlignment; String radioAlignment; String checkboxAlignment; String requiredCharacter; Boolean showNotProspect; Boolean isAlwaysDisplay; Boolean isCaptchaEnabled; Boolean isCookieless; String statusText; String errorMessage; } ``` ### Form Handler The Form Handler model represents an Account Engagement Form Handler. ```apex FormHandlerModel { Integer id; String name; Integer folderId; Integer campaignId; Integer trackerDomainId; Boolean isDataForwarded; String successLocation; String errorLocation; Boolean isAlwaysEmail; Boolean isCookieless; String statusText; String errorMessage; } ``` ### Dynamic Content The Dynamic Content model represents an Account Engagement Dynamic Content. ```apex DynamicContentModel { String name; Integer id; String baseContent; String basedOnProspectApiFieldId; Integer folderId; Integer trackerDomainId; List variations; String statusText; String errorMessage; } ``` ### Landing Page The Landing Page model represents an Account Engagement Landing Page. ```apex LandingPageModel { Integer id; String name; Integer campaignId; Integer formId; Integer layoutTemplateId; String title; String description; Boolean isDoNotIndex; String vanityUrlPath; String scriptFragment; String redirectLocation; Integer trackerDomainId; Integer folderId; String archiveDate; String content; String openingGeneralContent; String statusText; String errorMessage; } ``` ### Layout Template The Layout Template model represents an Account Engagement Layout Template. ```apex LayoutTemplateModel { Integer id; String name; String layoutContent; String formContent; Boolean isIncludeDefaultCss; Integer folderId; String statusText; String errorMessage; } ``` ### Flow Context The Flow Context model represents a GenerateFlowContext invocable action. ```apex FlowContextModel { Boolean isDefaultFlow = false; String accountEngagementSandboxBUCredential; String productionBusinessUnitId; String sandboxBusinessUnitId; Boolean productionToSandbox; } ``` ## Cross-Business-Unit Asset Copy Flow Walkthrough You can find the provided flow, **Account Engagement Bulk Asset Copy**, from **Setup** →**Flow**. This default flow provides a moderately complex example of how a copy flow is built. The flow just repeats the same basic pattern on multiple assets. The steps are: - Determine the Business Unit that contains the assets you want to copy, and the Business Unit that you want to copy those assets into - Select the assets to copy - Read the assets to copy - Configure the assets for copying - Create the copied assets To start, pull the available Business Units and select the source and destination. ![Select business units after the flow start step](https://developer.salesforce.com/docs/media/mcae_api_flow1.png) Next, pull the picklist values used for the rest of the flow. ![Add assets to the flow](https://developer.salesforce.com/docs/media/mcae_api_flow2.png) These queries are made to prepare for selecting and configuring the assets to copy. - Configuration - Campaigns - Folders - Tracker Domains - Assets - Email Templates - Custom Fields - Custom Redirects - Files - Engagement Studio Programs Select the assets to copy and validate to ensure a copy can occur. ![Select assets to copy screen in flow](https://developer.salesforce.com/docs/media/mcae_api_flow3.png) A screen presents a dropdown for each asset using a multi-select picklist, allowing for multiple options per dropdown. If any assets are selected, the process continues to read the assets. The following loops, repeated for each asset, pull the asset data from the source business unit. ![Flow loop](https://developer.salesforce.com/docs/media/mcae_api_flow4.png) The loop goes through each asset selected and reads its record from the source business unit, adding it to a new collection. The loop repeats for each asset so that all the data for copying is available for later steps. After all the information is read, summary information is presented to confirm the correct files are copied. From here, configure the campaign, folder, and tracker domain to use in the destination business unit. ![Configure campaign and folder in Flow](https://developer.salesforce.com/docs/media/mcae_api_flow5.png) The second set of loops go through each copy request and creates the record in the destination business unit. ![Copy assets in Flow](https://developer.salesforce.com/docs/media/mcae_api_flow6.png) The loop cycles through the selected asset records, using the field settings as input to the copy action. The final step records the new records ID and provides success confirmation. ![Confirm copy in Flow](https://developer.salesforce.com/docs/media/mcae_api_flow7.png) The same patterns apply for custom flows, only with a different set of loops to build a different bulk copy flow. With custom flows, you can also remove the loop to create copies one at a time. ## General Use Cases Note: We recommend an understanding of the standard flow before attempting a custom flow. ### Cross-Business-Unit Asset Copy Create a custom copy flow to move the right assets between business units. The standard process for a copy is to select the assets to copy, read the assets, and then create the assets using the read data. ### Integrate an External Builder Select an asset in an external location and copy it into Account Engagement. Note: This use case requires an invocable action be built for the external builder service to retrieve the desired content. After the content is received, the remainder of the flow is the same. 1. Configure the asset. 2. Create the asset. ### Embed an Asset into Another Asset Select an asset URL to embed into another piece of content. This use case is more advanced and requires development to parse and embed the desired content. However, it’s possible to read the URL for forms, files, and custom redirects to embed them into HTML. ## Package a Flow Flows built with API V5 for Flow can be packaged, so you can share them via AppExchange or make it easy to install into production. The process of packaging a flow is the same as other packages. Under Salesforce Setup, go to Package Manager, and follow these steps. 1. Create a package 2. Add components to the package 3. Select the type Flow Definition. 4. Select your desired Flow Definition. 5. Upload the package 6. Install via the provided URL # Authentication Prerequisites: 1. You must have [Salesforce OAuth set up](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_oauth_and_connected_apps.htm) in the org. To set up a connected app for OAuth, the "pardot_api" scope must be one of the selected OAuth scopes. Otherwise, OAuth flows other than username/password flow can't be used with the Account Engagement API. Check out this video for an example of how to implement OAuth. ::video{src="https://developer.salesforce.com/docs/marketing/pardot/guide/Bd9bUbJ8x1SezACaqnpPFB" title="Implement Salesforce OAuth for Account Engagement API" type="vidyard"} 1. You must have the Account Engagement Business Unit ID that you want to authenticate with. To find the Account Engagement Business Unit ID, use Setup in Salesforce. From Setup, enter "Business Unit Setup" in the Quick Find box. Your Account Engagement Business Unit ID begins with "0Uv" and is 18 characters long. If you can’t access the Business Unit Setup information, ask your Salesforce Administrator to provide you with the Account Engagement Business Unit ID. 2. Authenticate with a user that is SSO enabled. An SSO-enabled user is one who can log in to pi.pardot.com using "Log In with Salesforce" or who can access Account Engagement using the Account Engagement Lightning App. ## Oauth Authentication Domain by Account Type | **Account Type** | **Salesforce Domain** | **Account Engagement Domain** | | -------------------------------- | ---------------------- | ----------------------------- | | Production Account | `login.salesforce.com` | `pi.pardot.com` | | Account Engagement Developer Org | `login.salesforce.com` | `pi.demo.pardot.com` | | Sandbox | `test.salesforce.com` | `pi.demo.pardot.com` | ### OAuth 2.0 Flows There are numerous OAuth 2.0 Flow types supported. The [Web Server Flow](https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_web_server_flow.htm&type=5) is the most commonly used. For a list of all flows, see the [OAuth 2.0 Flows](https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_flows.htm&type=5) Help page. Read the descriptions of the flows to choose the best one for your case. ## Using Access Token with Account Engagement After you get the access token, you must pass it and the Account Engagement Business Unit ID using the `Authorization` and `Pardot-Business-Unit-Id` headers. ### Sample Request Request must be made using HTTPS. ```bash POST /api//version//do/ HTTP/1.1 Host: pi.pardot.com Authorization: Bearer Pardot-Business-Unit-Id: ``` ### Request Parameters | **Parameter** | **Required** | **Description** | | ------------------ | ------------ | ---------------------------------------------------- | | `access_token` | X | Access token obtained from Salesforce OAuth Endpoint | | `business_unit_id` | X | Account Engagement Business Unit ID | If a valid access token is provided with a valid business unit ID, the Account Engagement endpoint works as expected. Note: The Account Engagement API doesn’t enforce IP address restrictions that are configured using the Salesforce option "Enforce login IP ranges on every request". # Bulk Data Pull via the Account Engagement API This document outlines the approach and best practices for pulling large amounts of data out of Account Engagement via the API. ## Visitor Activity with Export API When you need large amounts of visitor activity data, use the Export API. If you need a different object, see [Query the Account Engagement API](#query-the-account-engagement-api) for details on how to retrieve the information using the query endpoint. The Export API is asynchronous and efficiently scales data retrieval based on the available resources. There are more server resources available for the Export API than the query endpoint, which provides faster results without hitting concurrency and API limits to process multiple queries. Before getting started, review the documentation for the Export API. ### Best Practice #1 - Polling for Status Updates Because export is asynchronous, you can poll the Read endpoint of the Export API to see if the export is done processing. The time an export takes depends on how much data is being exported and the resources available for processing. Because export times can vary, we recommend that you start by setting a polling interval between 30 seconds and a few minutes. If you run an integration regularly, set your polling intervals to the average of the time taken for a few runs of your integration. For example, if your integration runs daily and retrieves all visitor activity data for the previous day, start with a polling frequency of 1 minute. Note the export durations for a few days, then average those times to find a polling interval. In the example, over a few days you notice that your export finishes with an average duration of 15 minutes. Polling every minute is too often and polls 15 times. If you set the polling interval to 5 minutes, it polls three or four times. If you run integrations sporadically or infrequently, try increasing the polling interval over time. For example, if you track the number of times the integration has polled, you can calculate a gradually increasing polling interval using this function: ```bash ceil(((n * n)/5)+1) ``` Where `n` is the index of the poll, starting with 0 Using this function to calculate polling interval, you poll a minute the first time, 2 minutes for the second and continue to increase at larger intervals each time. This process allows the integration to check frequently soon after an export is created to catch the quick running exports but also limit the number of polls for exports that are long-running. Remember that the Read endpoint of the Export API counts toward API limits, so these tips let you adjust how much of that limit is used by your integration. ### Best Practice #2 - Specify Limited Date Ranges Because the results of the export API are returned only after the query has executed, limiting the date range of the export returns results faster. A way limit date range is to break large date ranges into several smaller ranges. For example, it's OK to create an export to retrieve a year's worth of visitor activity within a single export by specifying a year duration, like the following. ```powershell curl https://pi.pardot.com/api/export/version/3/do/create?format=json \ --H Authorization: Bearer \ --H Pardot-Business-Unit-Id: -d '{ "object": "visitorActivity", "procedure": { "name": "filter_by_created_at", "arguments": { "created_after": "2019-12-25 00:00:00", "created_before": "2020-12-25 00:00:00" } } }' ``` The issue is that all 12 months of data must be queried in order for the results to be returned. There are cases where your integration can use a smaller data set up front and be refined later as more data from the export becomes available. For example, an integration can work off the last month of data while waiting on a three-month range and then increasing to a twelve-month range. In this example, you could create three different exports with the three different ranges: Last month ```json "created_after": "2020-11-25 00:00:00", "created_before": "2020-12-25 00:00:00" ``` Three months prior ```json "created_after": "2020-08-25 00:00:00", "created_before": "2020-11-25 00:00:00" ``` Eight months prior ```json "created_after": "2019-12-25 00:00:00", "created_before": "2020-08-25 00:00:00" ``` Instead of waiting for all twelve months of data to be exported at once, the same data is returned in smaller increments, so you can see the newest data sooner. ## Query the Account Engagement API Pulling data from a query endpoint in the Account Engagement API is a straightforward, two-step process. First, log in with your Account Engagement user email, password, and user key to acquire an API key. Then, use the query endpoint for each data set to pull the data. Before getting started, review the object documentation and determine which data set you are going to pull. For a data set to be eligible for a bulk data pull, it must have a query operation that supports at least one of the following three sets of search filter criteria parameters: - `created_before` and `created_after` - `updated_before` and `updated_after` - `id_greater_than` and `id_less_than` Issue an HTTP GET to the appropriate query endpoint to pull the data back. The query response contains up to 200 rows from the data set you have requested. ### Best Practice #1 ‐ Use the Bulk Output Format For bulk data pulls, we strongly recommended that you use the `bulk` output format, which is highly optimized for performance. The `bulk` output format disables functionality that displays additional data in the API response such as nested object relationships (for example, campaign name for activities). Additionally, the bulk output format omits information about the total number of rows that matched your query, which enables the API to return a response more quickly. ### Best Practice #2 ‐ Avoid Offset For bulk data pulls, we strongly discourage use of the `offset` parameter. Instead, iterate through the data set using one of the supported search filter criteria parameters. As you process the query results in your code, store a high water mark value like the largest `id` or most recent `created_at` or `updated_at` value. Then, on your next query, send that high water mark value as the `id_greater_than`, `created_after`, or `updated_after` search filter parameter value. ### Bulk API Request & Response Samples Example Request & Response (XML) ```bash curl https://pi.pardot.com/api/visitorActivity/version/3/do/query?output=bulk \ --header Authorization: Bearer \ --header Pardot-Business-Unit-Id: ``` ```xml 1000 6789 100 1 Email Tracker
http://www.pardot.com/products/demos/flash-demo.html
555 1 2021-08-09 19:29:07
1001 6789 100 1 Email Tracker
http://www.pardot.com/products/demos/flash-demo.html
555 1 2021-08-09 20:13:40
``` Example Request & Response (JSON) ```bash curl https://pi.pardot.com/api/visitorActivity/version/3/do/query?output=bulk&format=json \ --header Authorization: Bearer \ --header Pardot-Business-Unit-Id: ``` ```json { "@attributes": { "stat": "ok", "version": 1 }, "result": { "visitor_activity": [ { "id": 1000, "visitor_id": 5678, "prospect_id": 100, "type": 1, "type_name": "Email Tracker", "details": "http://www.pardot.com/products/demos/flash-demo.html", "email_id": 555, "campaign_id": 1, "created_at": "2021-08-09 19:29:07" }, { "id": 1001, "visitor_id": 5678, "prospect_id": 100, "type": 1, "type_name": "Email Tracker", "details": "http://www.Account Engagement.com/products/demos/flash-demo.html", "email_id": 555, "campaign_id": 1, "created_at": "2021-08-09 20:13:40" } ] } } ``` ## Example of Paging through a Large Set of Results Because using the offset parameter is discouraged, let’s see how you can use a high water mark value to iterate through multiple pages of results instead. In this example, you query for all visitor activities that occurred yesterday. The `created_after` and `created_before` search filter criteria parameters are perfect for this use case. To keep things simple, assume there were a total of 5 activities created yesterday (at time of writing, 2016-03-29) at times 02:00, 06:00, 10:00, 14:00, and 18:00. Also assume the API page size limit is 2 rather than 200. To iterate over the results in the suggested approach, your API integration process would proceed as follows: 1. Log in to the Account Engagement API 2. Pull all visitor activity created after yesterday at midnight (`2016-03-29T00:00:00`) and before tonight at midnight (`2016-03-30T00:00:00`): Example Request & Response (JSON) ```bash curl https://pi.pardot.com/api/visitorActivity/version/3/do/query?output=bulk&format=json&created_after=2016-03-29T00:00:00&created_before=2016-03-30T00:00:00&sort_by=created_at&sort_order=ascending \ --header Authorization: Bearer \ --header Pardot-Business-Unit-Id: ``` ```json { "@attributes": { "stat": "ok", "version": 1 }, "result": { "visitor_activity": [ { "id": 1000, "created_at": "2016-03-29 02:00:00" }, { "id": 1001, "created_at": "2016-03-29 06:00:00" } ] } } ``` _Note_: The example was edited for brevity. 1. The API has returned two results - the activities from 02:00 and 06:00. Since you are paging by `created_at`, set your high water mark value to the `created_at` value of the last record you pull back, `2016-03-30T06:00:00`. You have now retrieved all activities up to that time. 2. Pull all visitor activity created after your high water mark (`2016-03-29T06:00:00`) and before tonight at midnight (`2016-03-30T00:00:00`): Example Request & Response (JSON) ```bash curl https://pi.pardot.com/api/visitorActivity/version/3/do/query?output=bulk&format=json&created_after=2016-03-29T06:00:00&created_before=2016-03-30T00:00:00&sort_by=created_at&sort_order=ascending \ --H Authorization: Bearer \ --H Pardot-Business-Unit-Id: ``` ```json { "@attributes": { "stat": "ok", "version": 1 }, "result": { "visitor_activity": [ { "id": 1000, "created_at": "2016-03-29 10:00:00" }, { "id": 1002, "created_at": "2016-03-29 14:00:00" } ] } } ``` _Note_: The example was edited for brevity. 5. The API returns two more results back - the activities from 10:00 and 14:00. Since you are paging by `created_at`, update your high water mark value to the `created_at` value of the last record you pull back, `2021-03-29T14:00:00`. You have now retrieved all activities up to that time. 6. Pull all visitor activity created after your high water mark (`2021-03-29T14:00:00`) and before tonight at midnight (`2021-03-30T00:00:00`): Example Request & Response (JSON) ```bash curl https://pi.pardot.com/api/visitorActivity/version/3/do/query?output=bulk&format=json&created_after=2021-03-29T14:00:00&created_before=2021-03-30T00:00:00&sort_by=created_at&sort_order=ascending \ --header Authorization: Bearer \ --header Pardot-Business-Unit-Id: ``` ```json { "@attributes": { "stat": "ok", "version": 1 }, "result": { "visitor_activity": [ { "id": 1001, "created_at": "2021-03-29 18:00:00" } ] } } ``` _Note_: The example was edited for brevity. 1. The API returns one result back, the activity from 18:00. As the max page size is 2 and the API returned one record, you know you are at the end of the list of records and do not need to query any further. If the API had returned 2 records you would repeat the query process again with a new high water mark. You know it’s safe to stop when the number of records returned by the API is less than the max page size. # Error Codes and Messages Use your error code or message to troubleshoot problems with the API. **tip:** Use CTRL+F to search this page for the error code or message you received. ## Error Responses in API Versions 3 and 4 In versions 3 and 4, errors are formatted as follows: ```xml error_message ``` ```json { "@attributes": { "stat": "fail", "version": , "err_code": "" }, "err": "Invalid action" } ``` ## Error Responses in API Version 5 In version 5, errors are formatted as follows: ```xml { "code": , "message": } ``` ## Numerical List of Error Codes ### Error Code: `1` **Message**: Invalid API key or user key **Problem**: Either the user or API keys are incorrect, or the API key has expired. **Solution**: Check the user and API keys in the request. If the user key was entered accurately, then submit a request for a new API key. ### Error Code: `2` **Message**: Invalid action **Problem**: The requested operation wasn’t recognized by the API. **Solution**: Verify that the requested operation is valid for the target object type. If that operation is allowed, then check for misspellings and other typos. ### Error Code: `3` **Message**: Invalid prospect ID **Problem**: Account Engagement couldn’t find a match for the provided prospect ID. **Solution**: Verify that the prospect ID is accurate. ### Error Code: `4` **Message**: Invalid prospect email address **Problem**: Account Engagement couldn’t find a prospect with the provided email address (for read, update, or delete), or the prospect email address is too long (> 255 characters) or has invalid syntax (for create/upsert). See [Allowed Characters in Email Addresses](https://help.salesforce.com/articleView?id=pardot_emails_allowed_characters.htm) for email address verification. **Solution**: If running create or upsert, verify the email address is valid. If running read, update, or delete, verify that a prospect with this email address exists in your Account Engagement instance. ### Error Code: `5` **Message**: Invalid query parameters **Problem**: Account Engagement didn’t recognize any of the provided search parameters. **Solution**: Check parameter spellings. Also, ensure that the specified search parameter is supported by the API. See [Parameters to Select Prospects](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md#parameters-to-select-prospects) for more details. ### Error Code: `6` **Message**: Invalid time frame **Problem**: The value of the `timeframe` search parameter wasn’t recognized. **Solution**: Check for misspellings in the `timeframe` value. Also, verify that the provided value is supported by the API. See [Parameters to Select Prospects](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md#parameters-to-select-prospects) for more for supported `timeframe` values. ### Error Code: `7` **Message**: Invalid timestamp **Problem**: Account Engagement couldn’t decipher a specified timestamp. **Solution**: Verify that the timestamp adheres to GNU standards for date and time input. See [GNU Date Input Format & Syntax](http://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html) for more information. Also, ensure all characters in the timestamp are URL safe. See [Parameters to Select Prospects](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md#parameters-to-select-prospects) for supported values. ### Error Code: `8` **Message**: Invalid time range **Problem**: The provided start timestamp is later than the end timestamp. **Solution**: Swap the values of the timestamps. ### Error Code: `9` **Message**: A prospect with the specified email address already exists **Problem**: The provided email address is already assigned to a prospect within Account Engagement. This error can occur when a `create` request with the same email address is submitted more than one time. **Solution**: Check the existing prospect record to see if data can be merged through an `update` request. ### Error Code: `10` **Message**: Invalid user ID **Problem**: The provided user ID doesn’t exist in Account Engagement. **Solution**: Verify that the user ID was typed correctly and matches the intended user in Account Engagement. ### Error Code: `11` **Message**: Invalid user email address **Problem**: The provided user email address couldn’t be found in Account Engagement. **Solution**: Verify that the provided email address belongs to a registered Account Engagement user and that it was typed correctly. ### Error Code: `12` **Message**: Invalid group ID **Problem**: The provided group ID doesn’t exist in Account Engagement. **Solution**: Verify that the group ID was typed correctly and matches the intended group in Account Engagement. ### Error Code: `13` **Message**: One or more required parameters are missing **Problem**: One or more of the required parameters for this type of request are missing. **Solution**: Verify that all of the required parameters have been provided. Check that all parameter names were spelled accurately and as specified in [Object Field References](https://developer.salesforce.com/docs/marketing/pardot/guide/object-field-reference.md). Ensure the proper URL punctuation was used, including `?` before parameters and `&` between parameters. ### Error Code: `14` **Message**: Non-existent prospect ID; No email address provided **Problem**: The ID provided for the `upsert` wasn’t valid, and no email address was provided for a new prospect to be created. **Solution**: Verify the provided ID. If creating a prospect was intended, ensure that an email address was provided. ### Error Code: `15` **Message**: Login failed **Problem**: The provided email address, password, or user key is invalid. **Solution**: Check the provided credentials for typos. Also, ensure that the specified user account has at least "Marketing" access privileges. ### Error Code: `16` **Message**: Invalid ID **Problem**: The provided ID isn’t valid. **Solution**: Ensure that only valid integer values were provided. ### Error Code: `17` **Message**: Invalid ID range **Problem**: The provided ID range isn’t valid. **Solution**: Swap the values of the specified IDs. ### Error Code: `18` **Message**: Invalid value for profile criteria matching status **Problem**: The provided value for a profile criteria's matching status wasn’t recognized. **Solution**: Ensure that only the values `match`, `nomatch`, or `unknown` are being used. ### Error Code: `19` **Message**: Invalid value specified for sort_by **Problem**: The provided value for the `sort_by` isn’t a supported sorting order. **Solution**: Check that the specified sorting values are listed in Using (Object Type): Supported Sorting Options section for the target object. ### Error Code: `20` **Message**: Invalid value specified for sort_order **Problem**: The provided value for the `sort_order` isn’t a supported sorting order. **Solution**: Ensure that only the values `ascending` or `descending` are being used. ### Error Code: `21` **Message**: Invalid value specified for offset **Problem**: The provided value for `offset` couldn’t be interpreted as an integer. **Solution**: Check for typos that can prevent the value from being interpreted. ### Error Code: `22` **Message**: Unsupported feature in this version of the API **Problem**: The feature requested by the API call isn’t implemented in this version of the API. **Solution**: Update the request to use the necessary API version. ### Error Code: `23` **Message**: Invalid value specified for limit **Problem**: The provided value for `limit` is invalid. **Solution**: Ensure that the provided value is an integer and is no larger than 200. ### Error Code: `24` **Message**: Invalid visitor ID **Problem**: The provided visitor ID doesn’t exist in Account Engagement. **Solution**: Verify that the visitor ID was typed correctly and matches the intended visitor in Account Engagement. ### Error Code: `25` **Message**: Parameter is_starred must be true or false **Problem**: The value specified for `is_starred` couldn’t be interpreted as a boolean. **Solution**: Verify that only the values `true` or `false` were specified. ### Error Code: `26` **Message**: Parameter assigned must be true or false **Problem**: The value specified for `assigned` couldn’t be interpreted as a boolean. **Solution**: Verify that only the values `true` or `false` were specified. ### Error Code: `27` **Message**: Parameter deleted must be true or false **Problem:** The value specified for `deleted` couldn’t be interpreted as a boolean. **Solution:** Verify that only the values `true` or `false` were specified. ### Error Code: `28` **Message**: Parameter new must be true or false **Problem:** The value specified for `new` couldn’t be interpreted as a boolean. **Solution:** Verify that only the values `true` or `false` were specified. ### Error Code: `29` **Message**: Invalid value specified for score **Problem**: The value specified for `score` couldn’t be interpreted as an integer. **Solution**: Check for typos that can prevent the value from being interpreted correctly. ### Error Code: `30` **Message**: Invalid score range specified **Problem**: The provided score range isn’t valid. **Solution**: Swap the values of the specified scores. ### Error Code: `31` **Message**: Invalid combination of parameters for score **Problem**: A conflicting set of query criteria for the prospect's score has been specified. **Solution**: Make sure that `score_equal_to` isn’t being used in combination with `score_greater_than` or `score_less_than`. ### Error Code: `32` **Message**: Invalid value specified for grade **Problem**: The value specified for `grade` isn’t one of the allowed options. **Solution**: Check for typos that may prevent `grade` from being interpreted correctly. See[Parameters to Select Prospects](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md#parameters-to-select-prospects) for supported values. Also, ensure that the specified grades are URL-encoded. ### Error Code: `33` **Message**: Invalid grade range specified **Problem**: The provided grade range isn’t valid. **Solution**: Swap the values of the specified grades. ### Error Code: `34` **Message**: Invalid combination of parameters for grade **Problem**: A conflicting set of query criteria for the grade has been specified. **Solution**: Make sure that `grade_equal_to` isn’t being used in combination with `grade_greater_than` or `grade_less_than`. ### Error Code: `35` **Message**: Invalid opportunity ID **Problem**: Account Engagement couldn’t find a match for the provided opportunity ID. **Solution**: Verify that the opportunity ID is accurate. ### Error Code: `36` **Message**: One or more required parameter values are missing **Problem**: Some of the parameters necessary to complete the specified API request were omitted from the request. **Solution**: Ensure that all required parameters have been included. In addition, check from typos in the parameter names. Also check that the request has been properly formatted. ### Error Code: `37` **Message**: A Salesforce connector was detected **Problem**: Your Account Engagement instance has a Salesforce connector. When a Salesforce connector is present, opportunities and prospect account cannot be modified by Account Engagement. **Solution**: **_(NOT RECOMMENDED)_** Deleting the Salesforce connector allows for opportunity modification to be done through the API. However, doing so disables synchronization with Salesforce. If a Salesforce connector is present, modifications to opportunities must be done within Salesforce. ### Error Code: `38` **Message**: Invalid campaign ID **Problem**: Account Engagement couldn’t find a match for the provided campaign ID. **Solution**: Verify that the campaign ID is accurate. ### Error Code: `39` **Message**: Invalid profile ID **Problem**: Account Engagement couldn’t find a match for the provided profile ID. **Solution**: Verify that the profile ID is accurate. ### Error Code: `40` **Message**: Invalid opportunity probability **Problem**: The value specified for `probability` isn’t valid. **Solution**: Ensure that the specified value is a number from 0 through 100 inclusive. ### Error Code: `41` **Message**: Invalid probability range specified **Problem**: The specified probability range isn’t valid. **Solution**: Ensure that the specified values are numbers from 0 through 100, inclusive. It might be necessary to swap the values of the specified probabilities. ### Error Code: `42` **Message**: Invalid opportunity value **Problem**: The value specified for `value` is not valid. **Solution**: Ensure that the specified value is a non-negative number. ### Error Code: `43` **Message**: Invalid opportunity value range specified **Problem**: The specified value range is not valid. **Solution**: Ensure that the specified values are non-negative numbers. It might be necessary to swap the specified values. ### Error Code: `44` **Message**: The provided prospect_id and prospect_email parameters do not match **Problem**: The specified `prospect_email` and `prospect_id` parameters do not correspond to the same prospect. **Solution**: Ensure that the specified email address and the ID both correspond to the desired prospect. Note: Typically, only one of these parameters is required. Consider omitting one of them. ### Error Code: `45` **Message**: The provided user_id and user_email parameters do not match **Problem**: The specified `user_id` and `user_email` parameters do not correspond to the same user. **Solution**: Ensure that the specified email address and the ID both correspond to the desired user. (Note: Typically, only one of these parameters is required. Consider omitting one of them.) ### Error Code: `46` **Message**: This API user lacks sufficient permissions for the requested operation **Problem**: The currently authenticated API user doesn't have the necessary permissions to perform the requested operation. **Solution**: Some API operations are only available to users with Administrative permissions. If the requested operation has such a requirement, reauthenticate as an administrative user and resubmit the request. See the [Authentication](https://developer.salesforce.com/docs/marketing/pardot/guide/authentication.md) section for more information. ### Error Code: `47` **Message**: Multiple assignment targets were specified **Problem**: More than one object was specified as a target for this `ASSIGN` request. For example, both a group and user were specified as targets of a prospect assignment. **Solution**: Ensure that only one target is specified when submitting an `ASSIGN` request. ### Error Code: `48` **Message**: Invalid visit ID **Problem**: The provided visit ID does not exist in Account Engagement. **Solution**: Verify that the visit ID was typed correctly and matches the intended visit in Account Engagement. ### Error Code: `49` **Message**: Access Denied **Problem**: User is not authorized to perform the requested operation either due to access restrictions or forbidden method of passing credentials **Solution**: Verify user has required access to perform the requested operation. Ensure that credentials are passed via a supported method as per the API documentation. Contact customer support if problem persists. ### Error Code: `50` **Message**: Invalid boolean **Problem**: Need a valid boolean value, like true. **Solution**: Make sure to use lowercase. ### Error Code: `51` **Message**: Invalid parameter **Problem**: Object type is invalid. **Solution**: Change the object type to one of the allowed types. ### Error Code: `52` **Message**: Invalid parameter range **Problem**: A parameter in the request is outside its acceptable range. **Solution**: Update the parameter to be within the acceptable range. ### Error Code: `53` **Message**: Client IP address/location must be activated before accessing API **Problem**: IP is not in the allowed list. **Solution**: Add the IP address to the allowed list to access the API. ### Error Code: `54` **Message**: Email address is already in use **Problem**: Email address is already being used by other prospect. **Solution**: Use different email address. ### Error Code: `55` **Message**: Invalid list ID **Problem**: You either did not specify the list ID, or that List ID doesn't exist. **Solution**: Specify an ID, or check to make sure using the correct ID. ### Error Code: `56` **Message**: Invalid number entered for field **Problem**: The value entered doesn't match the field's type of Number. **Solution**: Verify that there are no characters in the value. ### Error Code: `57` **Message**: Invalid date entered for field **Problem**: The value entered doesn't match the field's type of Date, it is an invalid format. **Solution**: Verify that the timestamp adheres to GNU standards for date and time input. See [GNU Date Input Format & Syntax](http://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html) for more information. Also, ensure all characters in the timestamp are URL safe. See [Supported Search Criteria](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md#prospect-query) in [Prospects](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md) for supported values. ### Error Code: `58` **Message**: That prospect is already a member of that list. Update the membership instead. **Problem**: The prospect is a member of the list already. **Solution**: Update the membership. ### Error Code: `59` **Message**: A CRM connector was detected **Problem**: Your Account Engagement business unit has a CRM connector. When a CRM connector is present, opportunities and prospect account cannot be modified by Account Engagement. **Solution**: **_(NOT RECOMMENDED)_** Deleting the CRM connector allows for opportunity modification to be done through the API. However, doing so disables synchronization with your CRM. If a CRM connector is present, modifications to opportunities must be done within your CRM. ### Error Code: `60` **Message**: Invalid HTTP request method **Problem**: The endpoint does not support the HTTP method of the request. **Solution**: Use the proper HTTP method for the endpoint. Reference object endpoint documentation or [Version 5 Overview](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/version5overview.md). ### Error Code: `61` **Message**: Invalid prospect account id **Problem**: Prospect Account ID was incorrect or doesn't exist. **Solution**: Verify that the prospect account ID was typed correctly and matches the intended Prospect Account in Account Engagement. ### Error Code: `62` **Message**: Conflicting Update **Problem**: Another update is occurring at the same time. **Solution**: Wait before performing this action. ### Error Code: `63` **Message**: Too many IDs specified **Problem**: There is a limit on how many IDs you can specify for this query. **Solution**: Lower the number of IDs you are querying for. ### Error Code: `64` **Message**: Email content missing required variables **Problem**: The content of the email is missing required variables. **Solution**: Ensure that all required variables, such as unsubscribe link, are present. ### Error Code: `65` **Message**: Invalid email format **Problem**: Doesn't have all required fields present or are not in proper format, such as from address. **Solution**: Ensure all fields are present, populated, and in proper format. ### Error Code: `66` **Message**: You have exceeded your concurrent request limit. Please wait, before trying again **Problem**: Have made too many requests in this time period. **Solution**: Wait a little before making more requests. ### Error Code: `67` **Message**: You have reached or exceeded the limit of how many of this type of object you may have. **Problem**: You have too many of the specified object type to create more. **Solution**: Delete some of the object if you must make more. ### Error Code: `68` **Message**: Template with this id does not exist. **Problem**: The template you are trying to access does not exist. **Solution**: Make sure you are using the correct template ID or create a one to use. ### Error Code: `70` **Message**: Batch processing is limited to 50 prospects at once. **Problem**: You are requesting to batch more prospects in an operation than we allow. **Solution**: Ensure that your batch request has 50 or fewer prospects. ### Error Code: `71` **Message**: Input needs to be valid JSON or XML **Problem**: You've inputted invalid JSON or XML. **Solution**: Ensure that your request is properly formatted. ### Error Code: `72` **Message**: JSON has been corrupted, hash does not match **Problem**: The encoded JSON has been corrupted at some point. **Solution**: Ensure that you are sending the correct information. ### Error Code: `73` **Message**: Currently there is not an Email Plug-in Campaign associated to successfully track this email. Please contact your Account Engagement administrator to ensure there is a proper campaign associated with the Account Settings in Account Engagement. **Problem**: Currently there is not an Email Plug-in Campaign associated to successfully track this email. **Solution**: Contact your Account Engagement administrator to ensure there is a proper campaign associated with the Account Settings in Account Engagement. ### Error Code: `74` **Message**: The email client is not supported by the plugin API **Problem**: The email client used is not supported by this API. **Solution**: Use an appropriate email client. ### Error Code: `75` **Message**: There was an error processing the request for the account variable tags **Problem**: There was an error processing the request for the account variable tags. **Solution**: Review the variable tags, and resubmit the request. ### Error Code: `76` **Message**: API access was disabled **Problem**: API access for your account has been disabled. **Solution**: Contact customer support. ### Error Code: `77` **Message**: Invalid prospect fid **Problem**: The provided Prospect FID was invalid. **Solution**: Provide a valid Prospect FID. ### Error Code: `79` **Message**: Invalid CRM_FID **Problem**: The CRM FID provided is invalid. **Solution**: Provide a valid CRM FID that can be accessed by your account, or is already attached to a prospect. ### Error Code: `80` **Message**: Invalid CRM_TYPE **Problem**: The CRM type provided or used is invalid. **Solution**: Specify a correct CRM type. ### Error Code: `81` **Message**: Prospect ID and FID do not match **Problem**: The provided Prospect ID and FID don’t match a single prospect. **Solution**: Provide a prospect ID and FID that match a single prospect. ### Error Code: `83` **Message**: No valid CRM connectors available **Problem**: Your account doesn’t have an available CRM connector. **Solution**: Add a CRM connector to your account. ### Error Code: `84` An error has occurred for which no reason is provided. ### Error Code: `85` **Message**: Unable to save the prospect **Problem**: For some reason, the prospect wasn’t saved. **Solution**: Resubmit the request or review the original request for errors. ### Error Code: `86` **Message**: Invalid Template id **Problem**: The template ID provided doesn’t correspond to a template. **Solution**: Provide a template ID that’s valid. ### Error Code: `88` **Message**: Your account must use version 4 of the API. **Problem**: You have requested version 3 of the API, but your account must use version 4. **Solution**: Make the request using `/version/4` in place of `/version/3`. ### Error Code: `89` **Message**: Your account is unable to use version 4 of the API. **Problem**: You have requested version 4 of the API, but your account must use version 3. **Solution**: Make the request using `/version/3` in place of `/version/4`. ### Error Code: `90` **Message**: Prospect array should be a flat array of attributes **Problem**: The prospect array given wasn’t a flat array, and it should have been. **Solution**: Resubmit the request with a flat array. See the Prospect Batch sections of the [Prospect object documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md) for examples. ### Error Code: `91` **Message**: Prospect array must be keyed by email address **Problem**: The prospect array given wasn’t keyed by email addresses, but should have been. **Solution**: Resubmit the request with an array keyed by email addresses. See the Prospect Batch sections of the [Prospect object documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md) for examples. ### Error Code: `92` **Message**: Prospect record could not be found **Problem**: The prospect record wasn’t found with the provided information. **Solution**: Resubmit the request with different parameters. ### Error Code: `93` **Message**: The selected template is missing send options **Problem**: Send options are required for the template. **Solution**: Resubmit the request with send options. ### Error Code: `94` **Message**: The provided version is not a valid number **Problem**: The version number used isn’t valid. **Solution**: Resubmit the request with a valid version number. ### Error Code: `95` **Message**: Folder name is invalid **Problem**: The name for the folder isn’t valid. **Solution**: Resubmit the request with a valid folder name. ### Error Code: `96` **Message**: User does not have access to this folder **Problem**: The role assigned for this user doesn’t have access to this folder. **Solution**: Update the users permissions and resubmit the request. ### Error Code: `97` **Message**: The folder ID provided does not exist **Problem**: No folder was found for the ID provided. **Solution**: Resubmit the request with a different folder ID. ### Error Code: `98` **Message**: Prospect not mailable **Problem**: One or more of the recipient prospects can’t receive the email requested (due to opting out, being flagged as "Do Not Email", or for other reasons) **Solution**: Check that the recipient list is correct, and that the prospect's email preferences are up to date. ### Error Code: `99` **Message**: User with the provided email already exists **Problem**: A user with the email provided is already in the system. **Solution**: Resubmit the request with a different email address. ### Error Code: `100` **Message**: The provided time zone is invalid **Problem**: The value provided does not match a valid time zone. **Solution**: Resubmit the request with a different time zone. ### Error Code: `101` **Message**: The provided role is invalid **Problem**: The value provided for role isn’t valid. **Solution**: Resubmit the request with a different role. ### Error Code: `102` **Message**: The CRM Username specified is currently applied to another user **Problem**: This CRM username is already in use and cannot be used for another user. **Solution**: Resubmit the request with a different CRM username to apply for the user. ### Error Code: `103` **Message**: A CRM connector was not detected **Problem**: A CRM connector was not found. **Solution**: Make sure to configure a valid CRM connector and try again. ### Error Code: `104` **Message**: The CRM Username specified was not detected **Problem**: The CRM username wasn’t found. **Solution**: Verify the CRM username provided is correct and try again. ### Error Code: `105` **Message**: There is no activation hash for the specified user **Problem**: The activation hash for the provided user wasn’t found. ### Error Code: `106` **Message**: User is already active **Problem**: The user is already activate. ### Error Code: `107` **Message**: Password does not meet requirements **Problem**: The submitted password doesn’t meet the password requirements. **Solution**: Resubmit the request using a password that meets the requirements. ### Error Code: `108` **Message**: This Asset cannot be deleted because it’s being used in other places. **Problem**: Unable to delete an asset if it’s used in other places. **Solution**: Remove all dependencies of this asset and try again. ### Error Code: `109` **Message**: The requested record was not found. **Problem**: Unable to find the requested resource. **Solution**: Verify the parameters are correct and resubmit the request. ### Error Code: `110` **Message**: Invalid Account Id **Problem**: Invalid account id submitted. **Solution**: Verify the account id is correct and resubmit the request. ### Error Code: `111` **Message**: The Integration Username specified is currently applied to another Account **Problem**: Unable to use the submitted username as it is already used. **Solution**: Resubmit the request using a different integration username. ### Error Code: `112` **Message**: Missing recipient to Track With Engage. **Problem**: The recipient parameter is missing. **Solution**: Resubmit the request with a valid recipient. ### Error Code: `113` **Message**: Missing CRM ID or Email Address of recipient. **Problem**: The request is missing required information. **Solution**: Resubmit the request with a valid CRM ID or email address. ### Error Code: `114` **Message**: Invalid CRM ID or Email Address of recipient. **Problem**: The CRM ID or email address is invalid. **Solution**: Resubmit the request with a valid CRM ID or email address. ### Error Code: `115` **Message**: Number of recipients is more than threshold. **Problem**: The number of recipients provided is too large. **Solution**: Resubmit the request with fewer recipients. ### Error Code: `116` **Message**: Request outdated. **Problem**: The request time has expired. **Solution**: Resubmit the request. ### Error Code: `117` **Message**: There was an error deleting the micro campaign. **Problem**: There was an error deleting the micro campaign. ### Error Code: `118` **Message**: This API can only be called in a test environment. **Problem**: This endpoint can only be called in a test environment. ### Error Code: `119` **Message**: Unable to create refresh tokens for Salesforce connector **Problem**: Unable to create a refresh token for the Salesforce connector for authentication. **Solution**: Resubmit the request to try again. If the problem persists, contact support. ### Error Code: `120` **Message**: Unable to verify Salesforce connector **Problem**: Unable to verify the Salesforce connector. **Solution**: Resubmit the request to try again. If the problem persists, contact support. ### Error Code: `121` **Message**: Unable to sync Prospect with Salesforce **Problem**: Unable to sync prospects with Salesforce. **Solution**: Resubmit the request to try again. If the problem persists, contact support. ### Error Code: `122` **Message**: Daily API rate limit met **Problem**: The daily allowed API requests have been met. **Solution**: Wait until the next calendar day for the daily limit to reset and try again. ### Error Code: `123` **Message**: Unable to verify Salesforce username; User may already have a verified Salesforce username. **Problem**: Unable to verify Salesforce username. **Solution**: Verify if the username has already been verified in the system. ### Error Code: `124` **Message**: Unable to set Salesforce username or id **Problem**: Unable to set the Salesforce username or id. **Solution**: Verify the Salesforce username or ID is correct and resubmit the request. ### Error Code: `125` **Message**: Cannot accept both user_id and crm_owner_fid. **Problem**: This request only accepts a user_id or crm_owner_fid but not both. **Solution**: Resubmit the request passing only a user_id or crm_owner_fid. ### Error Code: `126` **Message**: Invalid authentication mechanism **Problem**: This authentication method has been deprecated. **Solution**: Resubmit the request using a valid [authentication](https://developer.salesforce.com/docs/marketing/pardot/guide/authentication.md) method. ### Error Code: `128` **Message**: Cannot create campaigns **Problem**: Campaigns cannot be created for an account that has [Connected Campaigns](https://help.salesforce.com/articleView?id=sf.campaigns_pardot_alignment_parent.htm) enabled. **Solution**: Create a campaign in [Salesforce](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_campaign.htm). ### Error Code: `129` **Message**: Cannot modify campaign name or cost **Problem**: Campaign name and cost can't be modified via the API. **Solution**: Remove the name and cost fields from the request. ### Error Code: `130` **Message**: One or more of the specified fields are invalid **Problem**: One or more of the fields in the CSV is not a recognized standard or custom field. **Solution**: Ensure all of the column headers in the CSV match the headers in the [field reference](https://developer.salesforce.com/docs/marketing/pardot/guide/object-field-reference.md). Ensure the number of columns in the CSV matches the number of columns in the header row. ### Error Code: `131` **Message**: Your account is locked due to too many failed login attempts. Reset your password at https://pi.pardot.com/user/passwordReset **Problem**: Too many invalid api requests have been made. **Solution**: Reset your password at https://pi.pardot.com/user/passwordReset ### Error Code: `132` **Message**: Prospect is archived **Problem**: The prospect is in the recycle bin and can't be read. **Solution**: Undelete the prospect via the UI or choose another prospect. ### Error Code: `133` **Message**: Up to 2 sort by options are allowed. **Problem**: Too many columns were passed into the sort parameter. **Solution**: Use 2 or fewer sort by columns. ### Error Code: `134` **Message**: Up to 2 sort order options are allowed. **Problem**: Too many orders were passed into the sort parameter. **Solution**: Use 2 or fewer sort orders. ### Error Code: `135` **Message**: When passing a comma-separated value, one of the two values must be id. **Problem**: When sorting by multiple columns, one column must be the ID column. **Solution**: Add the ID column to the request. ### Error Code: `137` **Message**: URL is not valid. Please include a protocol (e.g., http:// or https:// ) **Problem**: An invalid URL was supplied in the request. **Solution**: Add one of the requested protocols to the request. ### Error Code: `138` **Message**: The supplied name contains too many characters. **Problem**: The name supplied was too long. **Solution**: Reduce the length of the name field. ### Error Code: `139` **Message**: The supplied name is not valid. **Problem**: The name field has an invalid character. **Solution**: Remove special characters from the name field. ### Error Code: `145` **Message**: Invalid archived parameter specified. Allowed values are true or false. **Problem**: The archived parameter only accepts boolean values. **Solution**: Update the request to send the proper boolean value. ### Error Code: `146` **Message**: Invalid archived parameter specified. Allowed values are true or false. **Problem**: The archived parameter only accepts boolean values. **Solution**: Update the request to send the proper boolean value. ### Error Code: `150` **Message**: Input needs to be valid JSON **Problem**: The JSON that was submitted was invalid. **Solution**: Submit valid JSON. A JSON linter may help ensure that the payload is valid before sending. ### Error Code: `151` **Message**: Unsupported content-type **Problem**: The 'Content-Type' header has an unsupported value for this endpoint. **Solution**: Check the documentation for the specific endpoint and ensure you are sending the correct Content Type value. ### Error Code: `152` **Message**: Request body can't be empty **Problem**: The API request has no body. **Solution**: Ensure that the payload of the request is being sent and is encoded as 'application/json' ### Error Code: `153` **Message**: Missing required property in request **Problem**: A required field in the request body could not be found. **Solution**: Check the documentation and ensure that all required fields in the request body are specified. ### Error Code: `154` **Message**: Invalid property in request **Problem**: A field in the request body has an invalid value. **Solution**: Check the documentation and ensure that the value that is being passed is supported. Several values are not supported at this time. ### Error Code: `155` **Message**: Can't update. Import must be in "Open" state. **Problem**: The import that is trying to be updated is not in the “Open” state. **Solution**: This import is no longer eligible to receive updates. Create an import, or update an existing import in the “Open” state. ### Error Code: `156` **Message**: Can't start processing. Import has no associated data. **Problem**: The import that is trying to be set to “Ready” has no data associated with it. **Solution**: Upload a batch of data before setting the import to “Ready”. ### Error Code: `157` **Message**: Error processing import request. Please contact your Account Engagement support representative **Problem**: The import has no background processing agent associated with it. **Solution**: This import was improperly created and is unsalvageable. Create an import and upload the same batch of data to ensure processing occurs. ### Error Code: `158` **Message**: Uploading a file was unsuccessful **Problem**: The “files” element of the request body could not be found. **Solution**: Ensure that the CSV being uploaded belongs to a key named “files”. ### Error Code: `159` **Message**: The file is not in a valid CSV format **Problem**: The CSV file is invalid. **Solution**: Ensure that the CSV file is properly formatted. There must be 1 header row, at least 1 data row, and the number of columns in each row must match the number of columns in the header. ### Error Code: `160` **Message**: The limit of batches per import has been reached **Problem**: Too many batches have been submitted for this import **Solution**: Create an import to submit this batch, or submit this batch to an import that has batch capacity. ### Error Code: `161` **Message**: The current state of the import does not allow the operation **Problem**: A batch was submitted to an import that is not “Open” **Solution**: Create an import to submit this batch, or submit this batch to an import that is “Open”. Processing is not affected for the import associated with the failed request. ### Error Code: `162` **Message**: No file was specified or uploaded **Problem**: No CSV file was submitted **Solution**: Submit a CSV file in the body of the request under the “files” key. ### Error Code: `163` **Message**: Too many files were specified or uploaded **Problem**: Problem: More than 1 file was submitted in a single request **Solution**: Submit only 1 file per request. ### Error Code: `164` **Message**: Daily limit of import batches has been reached **Problem**: Too many batches have been submitted over a 24-hour period. The account limit has been reached. **Solution**: Wait and try again later. ### Error Code: `165` **Message**: column options is invalid **Problem**: API input was incorrectly formatted. **Solution**: See documentation for correct input formatting. ### Error Code: `166` **Message**: The input is not in the required format **Problem**: The request input was not specified according to the documentation. **Solution**: Check the documentation for the desired endpoint and ensure the request is formatted properly. ### Error Code: `174` **Message**: Unknown procedure name. **Problem**: The provided procedure name does not exist. **Solution**: Check procedure name is spelled correctly or try another procedure name. ### Error Code: `175` **Message**: Unknown procedure argument. **Problem**: An unsupported argument was included in the procedure arguments. **Solution**: Check arguments are spelled correctly or remove unsupported argument. ### Error Code: `176` **Message**: Missing required argument. **Problem**: The export procedure is missing a requirement argument. **Solution**: Include the required argument in your procedure definition. ### Error Code: `177` **Message**: Invalid procedure argument. **Problem**: An invalid value has been provided for a procedure argument. **Solution**: Check the values provided for the procedure arguments are correct. ### Error Code: `178` **Message**: The current state of the export does not allow the operation **Problem**: The operation is not possible because of the state of the export. Possible reasons are that the export is expired or is still running. **Solution**: If the export hasn’t completed, wait until the read endpoint indicates that the export is complete before retrying the operation. ### Error Code: `180` **Message**: One or more of the specified fields are invalid **Problem**: One or more of the fields included in a create or update operation aren’t valid for that operation. **Solution**: Only include fields that are writable in the operation. ### Error Code: `181` **Message**: A required header is missing **Problem**: A required HTTP header is missing on the request. For example, if using Salesforce access tokens for authentication, the Pardot-Business-Unit-Id header must be included. **Solution**: Include the required header. ### Error Code: `182` **Message**: Invalid header value **Problem**: The value included in an HTTP header isn’t valid. It may be formatted incorrectly. **Solution**: Check documentation for the header. ### Error Code: `183` **Message**: An internal error occurred, please try your request again **Problem**: An internal error occurred. **Solution**: Try the request again. The error may have been related to a temporary condition such as a request failure between internal Account Engagement or Salesforce systems. ### Error Code: `184` **Message**: access_token is invalid, unknown, or malformed **Problem**: The access token passed in the Authorization header isn’t usable to make API requests to Account Engagement. **Solution**: Make sure the access token is formatted correctly and was obtained using a Connected App that includes the pardot_api OAuth scope. Make sure the user associated with the token is synced to the Account Engagement business unit. Make sure the token used is within its expiration time. ### Error Code: `188` **Message**: Provided import origin is invalid **Problem**: The import origin specified isn’t valid. **Solution**: Use "ui", "api", or "all" for the import origin. ### Error Code: `190` **Message**: Email sending is blocked for this account. **Problem**: The account has email sending blocked, and an email is being sent. **Solution**: Contact support. ### Error Code: `192` **Message**: Object specified does not exist **Problem**: The object ID specified in the API request doesn’t correspond to an object that exists. The object may have been deleted or the object ID passed in may never have been valid. **Solution**: Pass in a valid ID for an object that is not deleted or change the request to request a deleted object (one that is in the Account Engagement recycle bin). Use the deleted=true parameter in v5. ### Error Code: `193` **Description**: Too many subfields have been requested for one of the fields in the `fields` URL parameter for the API call. Account Engagement limits the number of fields that can be traversed when constructing an API response. ### Error Code: `194` **Message**: Invalid MIME type. **Problem**: The uploaded file isn’t of an allowed type. **Solution**: Upload a file of an allowed type. Make sure the extension of the file is appropriate for its type. ### Error Code: `197` **Message**: Import missing required field **Problem**: A required field is missing from your import. **Solution**: Include all required field in your import. ### Error Code: `198` **Message**: Endpoint not found **Problem**: We couldn't find that endpoint ID. Try again. **Solution**: Include a valid endpoint. ### Error Code: `199` **Message**: Authentication using an api_key is no longer supported. Use Salesforce OAuth access token instead. See https://developer.pardot.com/kb/authentication/ for details. **Problem**: The Account Engagement API doesn't support api_key based authentication. **Solution**: Salesforce OAuth endpoints should be used to retrieve an access token. See [Authentication](https://developer.salesforce.com/docs/marketing/pardot/guide/authentication.md) for details ### Error Code: `201` **Message**: Business Unit specified in Pardot-Business-Unit-Id header not found or inactive. **Problem**: The Business Unit ID is invalid or the business unit isn't active. This error is also returned when you use the wrong hostname (pi.pardot.com or pi.demo.pardot.com). **Solution**: Make sure that you're using a valid Business Unit ID for an active business unit, and that your URL contains the correct hostname. ### Error Code: `202` **Message**: Minute rate limit met **Problem**: The requested query execution timed out. **Solution**: Retry the query with a smaller window or try again later. ### Error Code: `203` **Message**: An admin user for the account not found. Ensure a user with the default admin role exists. **Problem**: There are no users with the default admin role. **Solution**: Make sure there is at least 1 user with the default admin role in Account Engagement. ### Error Code: `204` **Message**: File size exceeds the max post size or the body message can't be empty **Problem**: The file attached is larger than 50MB or has 0 bytes. **Solution**: Make sure the content of the file doesn’t exceed 50MB ### Error Code: `205` **Message**: Action name is either missing or incorrect **Problem**: The requested object doesn't support the requested record action. **Solution**: Check spelling and verify that the record action is available for the requested object. ### Error Code: `206` **Message**: Invalid action argument value **Problem**: The supplied value for the argument isn’t of the required data type. **Solution**: Make sure that the arguments are of the required data type according to the documentation. Strings must be enclosed by double quotes ("). ### Error Code: `207` **Message**: Missing required action argument **Problem**: One or more of the required arguments are missing. **Solution**: Make sure that you provide all of the required arguments for the requested record action. ### Error Code: `208` **Message**: Unknown action argument **Problem**: The supplied arguments to the record action are misspelled or invalid. **Solution**: Make sure that the arguments are spelled correctly and that they correspond to the arguments supported by the record action, according to the documentation. ### Error Code: `209` **Message**: Too many fields have filters: The max number of 3 distinct fields with filters was exceeded for this query. **Problem**: Too many fields in the request have filters. You can add filters to up to 3 fields. **Solution**: Decrease the number of fields with filters in the request. ### Error Code: `210` **Message**: Page token has expired. **Problem**: The page token is expired. Tokens are valid for 4 hours. **Solution**: Make sure you aren't using a page token that was issued more than 4 hours ago. ### Error Code: `211` **Message**: Page token is invalid. **Problem**: The token is null or invalid. **Solution**: Make sure the page token sent corresponds to the one provided by the last call's response. ### Error Code: `214` **Message**: API request timed out. **Problem**: The request timed out. **Solution**: Retry the query with smaller limits, offsets, or filter ranges. ### Error Code: `215` **Message**: Email form field is required. **Problem**: Email form field is required. **Solution**: Include an email form field. ### Error Code: `216` **Message**: Destination folder is full. **Problem**: The target folder for the object is full, and the object can't be created. **Solution**: Choose a different folder, or remove assets from the target folder. ### Error Code: `217` **Message**: Visitor is invalid. **Problem**: The visitor is invalid because `is_identified` is false or null on the visitor record, or `ipAddress` is null on the visitor record. **Solution**: Check the visitor ID or fix the `is_identified` or `ipAddress` fields on the visitor record. ### Error Code: `218` **Message**: Feature state is invalid: Connected Campaigns is not enabled for this business unit. **Problem**: Connected Campaigns isn’t enabled for the Account Engagement business unit. **Solution**: Enable [Connected Campaigns](https://help.salesforce.com/s/articleView?id=sf.campaigns_pardot_alignment_enable.htm). ### Error Code: `219` **Message**: Deleted records can't be updated. Please undelete before updating. **Problem**: The record that was targeted for update is in the recycle bin. **Solution**: Undelete the record and try again. ### Error Code: `220` **Message**: Invalid Available For selection **Problem**: This email template has false set for all of the following fields and at least one needs to be true: isOneToOneEmail, isListEmail, isAutoresponderEmail, isDripEmail. **Solution**: Ensure at least one of isOneToOneEmail, isListEmail, isAutoresponderEmail or isDripEmail is true. ### Error Code: `221` **Message**: Can’t delete the default template for Engage. **Problem**: The request attempted to delete the default Salesforce Engage template. **Solution**: Change the default Salesforce Engage template to another template and try again. ### Error Code: `222` **Message**: Can’t delete the default template for resubscribe emails **Problem**: The request attempted to delete the default resubscribe template. **Solution**: Change the default resubscribe template to another template and try again. ### Error Code: `223` **Message**: Unable to delete record **Problem**: The email template could not be deleted. **Solution**: Refer to the message in the response for more details. ### Error Code: `224` **Message**: Invalid fields for request type **Problem**: The request attempted to query non-queryable fields. **Solution**: Remove the invalid fields and try again. ### Error Code: `226` **Message**: Mismatched CSV headers and column options **Problem**: The CSV import file headers and the column options did not match. **Solution**: Update the column options to match the headers of the CSV import file and try again. ### Error Code: `227` **Message**: Mismatched CSV headers and field options **Problem**: The CSV import file headers and the field options did not match. **Solution**: Update the field options to match the headers of the CSV import file and try again. ### Error Code: `228` **Message**: The api call doesn't support mixed api versions **Problem**: The import was created with a different api version than was used with this request. **Solution**: Retrieve status updates for this import using the same api version it was created with. ### Error Code: `231` **Message**: Maximum file size has to be at least 10,000,000 bytes **Problem**: The maximum file size was set too low. **Solution**: Increase the maximum file size to be >= 10,000,000 bytes. ### Error Code: `232` **Message**: Maximum file size cannot exceed 200 MB **Problem**: The maximum file size cannot exceed your business unit's maximum file size. (Default 200 MB) **Solution**: See the error details for your business unit's maximum file size and set maximum file size to below the limit. ### Error Code: `233` **Message**: There is not a verified Salesforce connector **Problem**: There is not a verified Salesforce connector. **Solution**: Check your Salesforce connector and ensure it is verified and try again. ### Error Code: `234` **Message**: A v2 Salesforce connector is required for this action **Problem**: A v2 Salesforce connector is required for this action. **Solution**: Update the Salesforce connector to v2 and try again. ### Error Code: `235` **Message**: The Salesforce connector is already in the desired state **Problem**: The Salesforce connector is already in the requested state. **Solution**: The request is redundant so do not repeat it. ### Error Code: `236` **Message**: Select a list that is valid for this business unit **Problem**: The selected email list does not exist. **Solution**: Select a valid email list and try again. ### Error Code: `237` **Message**: Incorrect tag replacement language detected **Problem**: The tag replacement language was incorrect. **Solution**: Select a valid tag replacement language and try again. ### Error Code: `239` **Message**: File has been altered after initial download. **Problem**: The Engagement Studio export file was altered and cannot be used to recreate the Engagement Studio program. **Solution**: Export the Engagement Studio program and try again with the new file. ### Error Code: `242` **Message**: One or more requested records not found **Problem**: There were invalid tag ids present in the request. **Solution**: Remove the invalid tag ids and try again. ### Error Code: `243` **Message**: The sender address uses a domain that doesn’t exist or isn’t verified in your business unit. To send this email, add and verify the sending domain. **Problem**: The email address of the sender uses a domain that needs to be set up and/or verified in your business unit. **Solution**: Add and verify the relevant email sending domain(s) in your business unit. See (https://help.salesforce.com/s/articleView?id=sf.mcae_email_add_domain.htm&type=5) for details. ### Error Code: `244` **Message**: We couldn’t send your email. Review your email and try again. **Problem**: There was a temporary connection issue. **Solution**: Try again later. ### Error Code: `245` **Message**: The supplied name is already in use. **Problem**: The supplied name is being used by another record. **Solution**: Pick a different record name and try again. ### Error Code: `246` **Message**: We couldn’t send your email. Review your email and try again later. Issues with the recipient’s email address or service provider can prevent delivery. **Problem**: Your email likely has a delivery or content issue. For example, you forgot to add a sender address, the recipient’s address is invalid, or required text is missing. **Solution**: Review the sender address, recipient address, and required text. Fix any issues and try again. ### Error Code: 10000 ```xml ... ... ... ``` **Problem**: An error occurred when processing the parameter designated in the `param` attribute of the `` node. Several `` nodes may be contained within the `` node if multiple errors occurred. **Solution**: The `msg` attribute of each `` node should contain advice as to how to remedy the error. # Extend the Email Builder Experience This guide walks through ways to extend the email builder experience for your Account Engagement use cases. - Packaged email templates: Package your email templates to distribute on AppExchange. This use case is primarily for Independent Software Vendors, known as ISVs. - Custom Components for the email templates and email content: Custom components extend the building experience by providing a way to implement integrations and new standard building component types. ## Packaged Email Templates for Account Engagement A great email design is an easy way to increase prospect engagement and boost campaign effectiveness. A beautiful email in an easy-to-read format helps to set your marketing apart, and catches your prospects’ attention. However, creating a great email design isn’t easy and often requires skills that not all marketers have. Packaged email templates can help fill the gap. Instead of incurring the cost and expending the effort to create their own templates, a marketer can go to AppExchange and purchase ready-to-use templates designed by experts. Now a marketer can get templates in seconds and incorporate them into their next campaign. ### Considerations - Decide whether your primary goal is brand awareness or generating revenue. If the primary goal is brand awareness, then consider listing the templates as a free app. - Second-generation Packaging (2GP) isn’t supported for email template packaging. - The email template can be in an enhanced email template folder. - If a package includes an enhanced email template folder, the target organization must have enhanced folders enabled. - If an email template is in a subfolder, you must add the parent folder and the child folder to the email template package. - For merge fields based on custom fields that are used in the Recipients prefix (for leads and contacts), Account Engagement adds references to those merge fields. If the custom field is renamed, the reference in the template isn’t updated. To use the new field name and update the reference, edit the custom merge field in the template. ### Build a Packaged Email Template This overview provides the high-level steps to create packaged email templates. **note:** This process is intended for ISVs who want to list a package of email templates on AppExchange. If you’re a customer, you can follow a similar approach but we recommend using change sets for moving templates between orgs. 1. Use an Account Engagement sandbox to design your email template. If you're an ISV, then read the [Account Engagement ISV Getting Started Guide](https://developer.salesforce.com/docs/marketing/pardot/guide/isv/isv-getting-started.md) to learn how to sign up and get an Account Engagement developer environment. 2. Set up a user with the Access Drag and Drop Content Builder permission. Learn more in [Salesforce Help](https://help.salesforce.com/s/articleView?id=sf.pardot_eilex_setup_user_perms.htm). 3. Design and test the email templates using the Salesforce Email Template Builder. Learn more in [Salesforce Help](https://help.salesforce.com/s/articleView?id=sf.email_template_builder_parent.htm). 4. Package and list the templates on AppExchange. You need Salesforce developer environment to package templates and list an app on the AppExchange. [Learn More](https://go.demo.pardot.com/l/224232/2021-09-29/6q2xvz/224232/16329240531a9sHa0O/Packaging_Lightning_Email_Templates.pdf) Users then download the package and unpack the email template. Then they can use it as if it is their own. ## Custom Components for Email Templates and Email Content Custom components allow you to extend the email builders by developing Lightning Web Component (LWC) modules that can be embedded and configured within the builder canvas for email templates or email content. Overall, the goal of custom components is to provide marketers with reusable components that accelerate the design of a new email record. Here are the two most common use cases. - Integrating with an external source. Allows marketers to pull information or content quickly from another source to use within their email. For example: - Pull in webinar data and add it to the email automatically, bypassing manual steps, and avoiding errors. - To access content that isn’t stored in Salesforce, integrate an external CMS. - Reusable email formatting. Allows marketers to design an email with advanced components that aren’t standard. For example: - Create a data table component that allows marketers to easily embed tables into an email. - Create a reusable component that has an image, title, and text to make building the email quicker for common patterns. ### Considerations - Account Engagement doesn’t support scratch orgs. Although you can use Second-generation Managed Packaging (2GP) to develop the custom component, you can’t test email sends without a Account Engagement production org. ### Build a Custom Component This overview provides the high-level steps for building a custom component. 1. Use an Account Engagement sandbox to develop your custom component. If you're an ISV, then read the [Account Engagement ISV Getting Started Guide](https://developer.salesforce.com/docs/marketing/pardot/guide/isv/isv-getting-started.md) to learn how to sign up and get an Account Engagement developer environment. 2. Learn the basics of Lightning Web Components and set up your Salesforce DX Environment. See [Build Lightning Web Components](https://trailhead.salesforce.com/en/content/learn/trails/build-lightning-web-components) on Trailhead. 3. Set up email in your Account Engagement org to enable the new building experience within Account Engagement. See [Salesforce Help](https://help.salesforce.com/articleView?id=sf.pardot_eilex_setup_main.htm) for setup instructions. 4. Build an LWC custom component. See the [Custom Components Getting Started Guide](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_config_for_email_builder_custom_components). You can find an example of custom component code in [EmailBuildPoC](https://github.com/jrattanpal/EmailBuilderPoC) on GitHub. 5. Deploy and test your custom component in your Account Engagement sandbox or Account Engagement Developer org. 6. Package and deploy the custom component. - Option for ISVs: Package the custom component and list on AppExchange. See these resources for help: - Trailhead: [AppExchange Basics](https://trailhead.salesforce.com/en/content/learn/modules/appexchange_basics) - Salesforce Help: [About Managed Packages](https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/about_managed_packages.htm) - Salesforce Guide: [Application Installation Guide](https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/about_managed_packages.htm) (PDF) - Option for customers: Deploy the package into your org. Your customers can download the package, install, and configure it in their own orgs. Finally, they can add the custom components to their own email templates. # External Actions After you create a marketing app extension, you can create and configure an external action to use in Engagement Studio programs. External Actions relies on Salesforce invocable actions to work. You can use any [supported standard invocable action](https://help.salesforce.com/s/articleView?id=sf.pardot_external_actions_supported.htm), install one from AppExchange, or create a custom action. Here’s an overview of what’s required to create and use an external action. - Create, install, or select an invocable action that meets your use case. - Create and configure the external action. - Activate the action. - Use the action as a step in Engagement Studio programs. ## Considerations for External Actions Keep these considerations in mind when using External Actions. - Before you work with external actions, review the [considerations in Salesforce Help](https://help.salesforce.com/s/articleView?id=sf.pardot_external_actions_considerations.htm). - Standard and custom external actions often require you to edit the schema in Marketing Setup. - To protect your data, we recommend that you use only invocable actions that are created with Transport Layer Security (TLS). - If you’re using a supported standard or custom invocable action, you can edit the schema for the action to specify the fields that appear in Engagement Studio. - You can map input fields to HML merge fields so that they populate data from Account Engagement when the action executes. - Include the `Properties`, `View`, and `Required` sections in every action schema, even if there are no values in a section. - We recommend that you remove unnecessary fields from the View and Properties section of the action schema. Don’t remove fields from the Required section. - Changing or editing an action can affect all the Engagement Studio programs that the action is used in. - To trigger actions, the `IsActive` field on the action type and extension must be set to `true`. To set the `IsActive` field, select **Active in Automations** on each action type record in Setup. ## External Actions Authentication To create external actions via Tooling API, authenticate via Salesforce OAuth. You can also create external actions in Setup. Make sure to also set up authentication for Account Engagement in the third-party system that executes your external action. We recommend using an [authentication (auth) provider](https://help.salesforce.com/s/articleView?id=sf.sso_authentication_providers.htm) and a [named credential](https://help.salesforce.com/s/articleView?id=sf.named_credentials_about.htm). ## Create an Invocable Action External actions require a standard or custom invocable action. Before you configure an external action, create the invocable action for your use case. Invocable actions can be created through any of these methods: - [APEX InvocableMethod Annotation](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm) - [Salesforce Flow Builder](https://help.salesforce.com/s/articleView?id=sf.flow.htm) - [External Services](https://help.salesforce.com/s/articleView?id=sf.external_services.htm) You can also use any of the [supported standard invocable actions](https://help.salesforce.com/s/articleView?id=sf.pardot_external_actions_supported.htm) or install an action from a managed package. If you’re creating a custom invocable action, here are a few recommendations. - Build retry logic into your invocable action. External Actions don’t automatically retry when there’s a response delay from a third-party service. To allow time for retries, target a response time of 2 seconds. - For APEX invocable actions, use [custom exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_custom.htm) to provide error messages and avoid actions silently failing. You can also use a custom object to record the errors for an action. ## Grant Access to the B2BMA Integration User To use APEX invocable actions, including actions in Flow Builder, edit the APEX class to grant access to the B2BMA integration user. If your invocable action doesn’t use APEX, skip this section. 1. From Setup, in the Quick Find box, enter APEX, and then select APEX Classes. 2. Find your APEX class, and then click Security. 3. Select B2BMA Integration User and then use the arrows to add the user to the Enabled Profiles column. 4. Save your changes. **note:** If your invocable action was created via Flow Builder, you must also edit the permission set for the B2BMA Integration to give them access to flow. ## Create an External Action in Marketing Setup We recommend that you create and edit external actions from Marketing Setup. Work with your Salesforce admin to create the action. Then, come back here to learn how to edit the action’s schema for use in Engagement Studio. See [Add an External Action to a Marketing App Extension](https://help.salesforce.com/s/articleView?id=sf.pardot_external_action_add_action.htm). ## Customize an External Action Schema in Marketing Setup When you create an external action in Marketing Setup and select an invocable action, the schema field is automatically populated. The schema is written in JSON and controls what appears when someone adds the action as a step in Engagement Studio. It also controls what happens when the action executes. **note:** Action types also include a Parameters field for the invocable action. To ensure the action functions properly, don’t edit this field. ### About Action Schemas Schemas have three main sections: - **Properties**: Fields in this section define how the action behaves. All the fields that you include in the other sections must also be present in this section. - **View**: Fields in this section are editable in the Engagement Studio step. - **Required**: Fields in this section are mandatory for the invocable action to work. You can’t remove any fields that appear in this section by default. All three sections must be present for the action to function properly, regardless of whether there are field values in each one. ### Step 1: Open the Action Type for Editing From Marketing Setup, open a marketing app extension, and then edit an action type. We recommend expanding the Invocable Action Schema field for easier editing. **note:** If the invocable action you’re using was installed from a managed package, the schema can’t be edited. ### Step 2: Set Default Values for Fields You can specify default values for fields in the Properties section. If a field is also in the View section, the value you specify is editable when the action is added in Engagement Studio. If the field appears only in the Properties section, it’s a static default that appears when the action executes. Supported data types include number and string. - To create a boolean field, use the `number` data type and set the maximum value to `1`. The system casts this configuration to a boolean field when it executes the action. - If your invocable action uses an integer, change the data type in the external action schema to `number`. The system casts this configuration to an integer when it executes the action. In this example, we set a default value for the Source field to show as Account Engagement. ```json "properties": { "firstName": { "type": "string", "title": "Source", "value": "Account Engagement" } } ``` To make a field editable in Engagement Studio, include the field in the View section. ### Step 3: Populate Fields with Account Engagement Data Use HML merge fields to populate fields in the action. Map fields that appear in the schema to HML merge fields that fit your needs. In this example, we use the HML field `{{Recipient.FirstName}}` and map it to the `firstname` field in the schema. When the action executes to register a prospect for our webinar, it passes the prospect’s first name from Account Engagement to the webinar provider. ```json "properties": { "firstName": { "type": "string", "title": "First Name", "value": "{{Recipient.FirstName}}" } } ``` For more information about HML merge fields and Account Engagement data, see [Handlebars Merge Fields in Account Engagement](https://help.salesforce.com/s/articleView?id=sf.pardot_handlebars_merge_fields.htm). ### Step 4: Add or Remove Fields from the View Section Fields in the View section are displayed to marketing users when they add the action in Engagement Studio. To define which fields are editable in Engagement Studio, add or remove fields from this section. In this example, we want our marketing users to enter the business unit ID and the campaign ID when they add our action to an Engagement Studio program. ```json "view": { "components": [ { "definition": "lightning/control", "scope": "#/properties/businessUnitId" }, { "definition": "lightning/control", "scope": "#/properties/campaignId" } ] } ``` ### Step 5: Add Fields to the Required Section To make optional fields mandatory for your external action, add them to the Required section. To make fields visible to marketers, you must also add them to the View section. For example, if you want marketers to provide the `campaignID` when they add the action in Engagement Studio, include that field in both the `Required` and `View` sections. **important:** You can add fields to the Required section, but don’t remove any fields that are already present. Those fields are necessary for the invocable action to work. ### Step 6: Remove Unnecessary Fields To reduce clutter and make your action easier to use, remove any fields you don’t need from the Properties and View sections. To ensure the invocable action executes properly, don’t remove fields from the Required section. ### Step 7: Activate the Action After your action is configured the way you want it, select Active in Automations on the record and save your changes. ![Screenshot of the checkbox to activate the record.](https://developer.salesforce.com/media/pardot_external_action_activate.png) When an action is activated, it’s available to use when you add an action step in Engagement Studio with the inputs you specified in Step 4. ![Screenshot of an action in Engagement Studio.](https://developer.salesforce.com/media/pardot_es_external_action.png) ## Use Tooling API to Configure an Action In general, we recommend creating and editing external actions from Marketing Setup. However, you can create actions using [Tooling API](https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/tooling_api_objects_marketingappextaction.htm). To add an action type to your marketing app extension, send a POST request to the `MarketingAppExtAction` endpoint. ``` POST /services/data/v55.0/tooling/sobjects/MarketingAppExtAction HTTP/1.1 Host: YOUR_DOMAIN Authorization: Bearer YOUR_ACCESS_TOKEN Content-Type: application/json Content-Length: 1183 { "ActionName": "Register for Spring Webinar", "ActionParams": "{\n \"isStandard\": false,\n \"type\": \"apex\"\n}", "ActionSchema": "{\n \"properties\": {\n \"email\": {\n \"type\": \"string\",\n \"title\": \"email\",\n \"value\": \"{{Recipient.Email}}\"\n },\n \"firstName\": {\n \"type\": \"string\",\n \"title\": \"firstName\",\n \"value\": \"{{Recipient.FirstName}}\"\n },\n \"lastName\": {\n \"type\": \"string\",\n \"title\": \"lastName\",\n \"value\": \"{{Recipient.LastName}}\"\n },\n \"webinarId\": {\n \"type\": \"string\",\n \"title\": \"webinarId\",\n \"value\": \"\"\n }\n },\n \"view\": {\n \"components\": [\n {\n \"definition\": \"lightning/control\",\n \"scope\": \"#/properties/webinarId\"\n }\n ]\n },\n \"required\": [\n \"email\",\n \"firstName\",\n \"lastName\",\n \"webinarId\"\n ]\n}", "ActionSelector": "MktgExtAction__VidYardApiRequest", "ApiName": "VidYard_Add_to_Webinar", "Description": "Registers the prospect for the given Webinar ID.", "IsActive": true, "MarketingAppExtensionId": "0mF8X0000008OIyUAM" } ``` To configure the action, define the invocable action and schema fields. Use the `ActionSelector` field to identify your invocable action, then provide the fields and values for the action schema. - Include all the fields required for your action to execute in the Required section. Add any additional fields that you want marketers to provide values for when they add the step in Engagement Studio. - Define default values for fields in the Properties section. Use HML merge fields to automatically populate fields with Account Engagement data. - Add fields to the View section that you want to be editable in Engagement Studio. To activate your action for use in Engagement Studio, set the `IsActive` field to `true`. The associated Marketing App Extension must also be active for automations. For more information about editing action schemas, see the [Customize an External Action section](#customize-an-external-action-schema-in-marketing-setup) of this guide. A successful request returns a `201 Created` response that contains information about the request. ``` { "id": "2Yo8X000000000pSAA", "success": true, "errors": [], "warnings": [], "infos": [] } ``` ## See Also - _Trailhead_: [Extensibility Features for Account Engagement](https://trailhead.salesforce.com/content/learn/modules/pardot-external-activities-quick-look) # External Activity After you set up an extension, submit a request to create an activity type record. Then, submit a request to pass prospect activities to Account Engagement as they occur. ## Considerations Keep these considerations in mind when working with External Activity. - Before you work with external activities, review the [considerations in Salesforce Help](https://help.salesforce.com/s/articleView?id=sf.pardot_external_activity_considerations.htm). - The `DeveloperName` field from the MarketingAppExtension endpoint maps to the extension field on the external-activities endpoint used to submit the activity. - The DeveloperName field from the MarketingAppExtActivity endpoint maps to the type field on the external-activities endpoint used to submit the activity. - To submit activities, the `IsActive` field on the activity type and extension must be set to `True`. To set the `IsActive` field, select **Active in Automations** on each record in Setup. - We recommend waiting to make an activity type active until you’re ready to begin using them. - Activities are only submitted to the business unit assigned to the extension. Changing the business unit can affect your integration. ## External Activity Authentication To work with external activities, authenticate to Account Engagement API and Tooling API using OAuth. Make sure that the appropriate OAuth Scopes are set up in your connected app: - **Access Account Engagement services (pardot_API)** - **Manage user data via APIs (API)** To minimize the number of times you have to authenticate, grant new access tokens as they expire by adding the **Perform requests on your behalf anytime (refresh_token, offline_access)** scope. ## Configure an External Activity To add an activity type to your marketing app extension, send a POST request to the `MarketingAppExtActivity` endpoint. In this example, we configure an activity type “registered” for the extension we set up in the Marketing App Extensions section. ``` POST /services/data/v55.0/tooling/objects/MarketingAppExtActivity HTTP/1.1 Host: YOUR_DOMAIN Authorization: Bearer YOUR_ACCESS_TOKEN Content-Type: application/json Cookie: YOUR_COOKIE_ID CookieConsentPolicy=0:0 Content-Length: 187 { "DeveloperName": "registered", "MasterLabel": "Registered for Webinar", "MarketingAppExtensionId" : "01234567890123MAA", "IsActive" : "true", "Description": "An event for registration" } ``` A successful request returns an `201 Created` response. ## Submit External Activity Data To submit activity data, send a POST request to the `/api/v5/external-activities` endpoint. ``` POST /api/v5/external-activities HTTP/1.1 Host: Authorization: Bearer Content-Type: application/json Content-Length: 107 { "extension": "webinar", "type": "registered", "email": "demo@test.com", "value": "Webinar 2" } ``` **note:** - The extension value in the example is the DeveloperName returned from the Marketing App Extension response. - The type value in the example is the DeveloperName returned from the Marketing App Extension Activity Type response. ## See Also - _Trailhead_: [Extensibility Features for Account Engagement](https://trailhead.salesforce.com/content/learn/modules/pardot-external-activities-quick-look) # Get Started as an Account Engagement ISV Account Engagement, Salesforce’s B2B marketing automation tool, is designed to help businesses of every size: - Find more leads and convert them faster with content that resonates. - Engage buyers on their terms with tailored, relevant campaigns. - Deliver connected experiences by aligning marketing, sales, and service teams so that they can win deals and build customer loyalty. - Act on insights by tracking marketing performance all in one place. Watch a [demo](https://www.salesforce.com/form/conf/demo-pardot/) for more insight into Account Engagement. ## Getting Started Resources - Trailhead: [Marketing Cloud Account Engagement Basics](https://trailhead.salesforce.com/content/learn/modules/pardot-basics-lightning) - Account Engagement Developer Docs: [Marketing Cloud Account Engagement API: Quick Look](https://trailhead.salesforce.com/content/learn/modules/pardot-api-quick-look) - Sign up for [the Partner Community](https://partnersignup.salesforce.com/) - Join the [Partner Community for Account Engagement](http://p.force.com/pardotgroup) Chatter Group ## Account Engagement Pricing & Licensing [Account Engagement Pricing](https://www.pardot.com/pricing/) ## Become an Account Engagement Partner or Product Development Outsourcer (PDO) Becoming an Account Engagement App Partner allows you to develop and sell solutions on AppExchange. Becoming a PDO lets you consult and build Account Engagement apps for ISVs and other customers. ## Become an Account Engagement AppExchange Partner Becoming an Account Engagement App Partner is an opportunity to help grow your company by integrating with an industry leader and gain exposure to Account Engagement’s users. The ISV partner program not only provides increased exposure by listing on Salesforce’s AppExchange but also opens up opportunities for co-selling & co-marketing opportunities. The only partner program that Account Engagement supports is the ISVForce program. Account Engagement doesn’t support the other AppExchange Partner Programs, like OEM or VAR. Review these resources to learn more about becoming a partner: - [Get Started with the AppExchange Partner Program Trailhead module](https://trailhead.salesforce.com/content/learn/modules/isvforce_basics/isvforce_basics_partner_program) - [AppExchange Partner Program Main Site](https://1.appexchange.com/partnerprogram) - [General ISV Onboarding Guide](https://www.salesforce.com/en-us/wp-content/uploads/sites/4/documents/partners/readiness/appexchange_isv_onboarding_guide.pdf) ## FAQ ### If I’m a Salesforce Consulting Partner, do I have to join another Partner program? Yes, you must join the AppExchange Partner Program. ### If I’m a AppExchange Partner already, do I have to join another Partner program? No. If you’re part of the AppExchange Partner program, building an Account Engagement app is like launching any other app. ### What if I have a Salesforce app for my product? If I integrate with Account Engagement, is that another revenue share agreement? Depends on the business model of the app. Generally, the revenue share is per the cost of the app. **How do I access an Account Engagement dev environment to begin development?** AppExchange Partner and Consulting Partner Option: - Create an Account Engagement Developer Environment via instructions in the [Account Engagement Partner Community Forum](https://partners.salesforce.com/_ui/core/chatter/groups/GroupProfilePage?g=0F9300000009O3oCAE). Non-Salesforce Partner options: - Work with a customer. - Purchase an Account Engagement production business unit. - Work with a Product Developer Outsourcer (PDO). ### How do I list an existing Account Engagement integration on the AppExchange? Register to become an AppExchange (ISV) Partner and start the process to make an AppExchange listing. ## Becoming a Product Development Outsourcer (PDO) A Product Development Outsourcer (PDO) is an app building expert who can provide services to ISVs who want to build Account Engagement apps for their product. A PDO can consult with an ISV on how to design the application or provide the development force to build the app for them. Overall, any marketing technology solution could benefit from an integration with Account Engagement, which means there are over 8,000 potential ISVs that could need an integration. Because a PDO is a specialized type of consultant, the first step to becoming a PDO is to join the Salesforce Consulting program: - [Consulting Partner Program](https://partners.salesforce.com/s/education/consultants/Consulting_Partner_Program) - If you're planning to focus on Account Engagement, we recommend these certifications: - Pardot Consulting - Platform Developer I The Account Engagement PDO is a subspecialization of the Salesforce PDO program. To learn more about the PDO program review these resources: - [PDO Approval Process](http://p.force.com/pdo) - [Navigator Program Details](http://p.force.com/navigator) The requirements for becoming a PDO are: - One completed project - One Pardot Consultant Certification - One project tagged with Pardot Specialization ### FAQ #### If I’m an existing Salesforce Consulting Partner, do I have to sign up for another partner program? No, since you’re already a Consulting Partner there are no additional fees to also become a PDO. ## Account Engagement Extensibility Features The following are the key features available to you to build an Account Engagement app: - Account Engagement API - Account Engagement-related Salesforce API endpoints - Custom Email Builder Components - Packaged email templates - Salesforce components - Marketing Extensibility Features ### Account Engagement API The Account Engagement API provides access to Account Engagement data and services for integration with other systems. For details on what the Account Engagement API supports, review the [Account Engagement API Documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/overview.html#getting-started). Here are some example use cases. #### External Segmentation Account Engagement customers often have valuable marketing data outside of their marketing automation solution, such as a CDP or consent tool. An ISV can create a service that allows the customer to segment a population and then upload that segment to Account Engagement for automation and nurturing. These solution types mostly use the [prospect](https://developer.salesforce.com/docs/marketing/pardot/v4/prospects-v4.md), [custom fields](https://developer.salesforce.com/docs/marketing/pardot/v4/custom-fields-v4.md), [lists](https://developer.salesforce.com/docs/marketing/pardot/v4/lists-v4.md), and [list membership](https://developer.salesforce.com/docs/marketing/pardot/v4/list-memberships-v4.md) API endpoints. #### Data Sync and Data Integrations Customers want to export Account Engagement data to an external data store. The use cases are varied but primarily are choosing the related data objects available via the API. An ISV service can sync a set of data or provide a data connector to a specific set of applications. #### Publish to Account Engagement API v5 enables publishing to Account Engagement functionality for files, landing page layout templates, and custom redirects. The general use case is a content creation service that wants to create an option to publish from their solution into Account Engagement. #### External Activity and External Actions Submit prospect engagement activity that occurs in an external system or automatically take action on prospects outside of Account Engagement. Data from active external activities is available to use in automation rules, segmentation rules, and Engagement Studio programs. Active external actions are available only in Engagement Studio programs. Review the [extensibility features guide](https://developer.salesforce.com/docs/marketing/pardot/extensibility/extensibility-features-overview.md) for more details about this feature. ### FAQ #### How do you authenticate to Account Engagement’s API? Account Engagement uses Salesforce OAuth Flows for authentication and requires a connected app with the Account Engagement API default scope. Account Engagement requests require an authentication header with the access token and a header with which business unit to access. [Learn more about authentication](https://developer.salesforce.com/docs/marketing/pardot/guide/authentication.html). #### When should I consider the Import / Export API vs. the Synchronous API? - When your goal is to transfer a large volume of data to or from Account Engagement, 10,000 records or more, consider using the export and import APIs. - When you don't require real-time or near-time data freshness. ### Considerations #### Environments When developing apps consider adding support for different Account Engagement environments, giving your customers the ability to test in non-production environments. | Type | Salesforce Domain | Account Engagement Domain | | ------------------ | -------------------- | ------------------------- | | Production Account | login.salesforce.com | pi.pardot.com | | Developer Org | login.salesforce.com | pi.demo.pardot.com | | Sandbox | test.salesforce.com | pi.demo.pardot.com | If you’re also using the Salesforce API, then make sure you factor [My Domain](https://help.salesforce.com/articleView?id=domain_name_overview.htm) into your domain. The domain is returned as part of the login request in the field “instance_url”. #### Business Units - Customers can have multiple instances of Account Engagement, which are called business units. Any app you create must be able handle multiple business units. For example, one customer wants to pull all business unit data into your app, while another customer wants to pull data from a single business unit. - Account Engagement API requests can only be made against one business unit at a time. Which business unit is accessed is determined by the Business Unit ID added into the header of the request. The Business Unit ID is found in Marketing Setup > Business Unit Setup. #### API Versions - Whether a customer uses v3 or v4 of the API depends on whether their account [allows multiple prospects with the same email address](https://help.salesforce.com/s/articleView?language=en_US&type=0&id=pardot_admin_ampsea_parent.htm). For this reason, we recommend that you build apps that support both versions. - To identify whether a customer uses v3 or v4, submit to v4 first, because the majority of customers are on this version. If the customer is on v3 you receive error code 89: “Your account is unable to use version 4 of the API”. - API v5 can be used by any account. ### Account Engagement-Related Salesforce Endpoints To help you align marketing and sales teams, Account Engagement is tightly integrated with Sales Cloud. This integration opens up multiple Salesforce endpoints that can be used to interact with Account Engagement features. [See a list of related endpoints](https://developer.salesforce.com/docs/marketing/pardot/guide/sf-endpoints.html#account). #### Account Engagement & Salesforce Sync Process Before deciding whether to use Salesforce endpoints or Account Engagement endpoints, you must understand Account Engagement sync behavior. Account Engagement syncs many objects with Salesforce to provide sales and marketing alignment. Here are the key sync-related objects: | Type of sync | Object | Details | | --------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Bidirectional | Prospect | A prospect is a record in Account Engagement that represents an individual. Prospects sync with leads, contacts, and person accounts in Salesforce. Account Engagement can create, read, and update lead and contact records. An email address is required for sync. Prospects sync with Salesforce ID as the unique identifier, and email can be used as a secondary match criteria. When a lead converts to a contact, Account Engagement maintains the prospect record and updates the Salesforce ID. | | Read-only | Accounts | Accounts in Account Engagement represent companies, groups, or organizations. Accounts in Account Engagement sync with accounts in Salesforce. Account Engagement can read account objects in Salesforce. Account Engagement automatically syncs with accounts that are associated with syncing contacts. | | Read-only | Opportunities | Opportunities in Account Engagement represent companies, groups, or organizations. Opportunities in Account Engagement sync with opportunities in Salesforce. Account Engagement can read opportunity objects in Salesforce. Account Engagement automatically syncs with opportunities that are associated with syncing contacts via contact roles. Contact role is a junction object that links to both the contact and the opportunity record. | | Limited Bidirectional | Campaign Members | Prospects in Account Engagement can be added to Salesforce campaigns in order to track engagement with marketing programs. This action creates a campaign member record in Salesforce. Campaign members are simply leads or contacts that belong to a campaign. Account Engagement can create, read, and update campaign member records and campaign member status. Account Engagement can also read the campaign object in order to add a campaign member to the campaign. Account Engagement campaigns and Salesforce campaigns are different objects that don’t sync directly by default, however you can connect them to streamline management. | | Limited Read-only | Custom Objects | Custom objects in Account Engagement are used to track objects that aren't native to your business unit. If you've purchased the custom object integration, you can sync with additional objects in Salesforce. Account Engagement can read custom objects that are directly linked to a lead, contact, or account record. Syncing too many custom object records or fields can significantly slow down your business unit. Sync only custom objects that are vital for your segmentation goals. | This diagram provides an overview of the high-level architecture for sync: ![Image that displays an architecture diagram](https://developer.salesforce.com/media/pardot/sync%20architecture.png) In the diagram, an Account Engagement prospect syncs bidirectionally to Salesforce lead and contact records. Leads and contacts sync bidirectionally to the Salesforce campaign object. Custom objects sync one way to lead, contact, and account records. Opportunities sync one way to contact records. Now, let's walk through the basic logic that determines how a prospect syncs to Salesforce. 1. Is there a lead or contact with the same CRM ID? - Yes: Sync with lead or contact. - No: Go to step 2. 2. Is there a contact with the same email address? - Yes: Sync with contact. - No: Go to step 3. 3. Is there a lead with the same email address? - Yes: Sync with lead. - No: Go to step 4. 4. Is the prospect assigned to a user? - Yes: Create a lead. - No: Keep record in Account Engagement until it's assigned to a user. Keep these considerations in mind when deciding to use Salesforce endpoints or directly use the Account Engagement endpoints: - Is the primary purpose to add marketing data to a prospect? If so, then write directly to the Account Engagement prospect. Customers don’t often sync all marketing fields to the lead or contact, so updating prospects directly ensures up-to-date data. - How urgently do you need the data to meet marketing goals? Sync does introduce a few minute delay between data being sent and the data being used in Account Engagement. ### Account Engagement-Related Salesforce Endpoints Example Use Cases #### Setting Up Campaigns Campaigns allow marketers to manage outbound marketing campaigns with direct mail programs, seminars, print ads, email, and other kinds of marketing collateral. Campaigns can be organized into hierarchies for easy analysis to see what works best for increasing sales. The Salesforce APIs can be used to create a campaign and assign lead or contacts as campaign members to set up a new marketing effort. For example, create a campaign in an external service to track costs for marketing efforts outside of Salesforce while still getting a complete view of marketing attribution within Salesforce. **note:** Account Engagement customers must enable [Connected Campaigns](https://help.salesforce.com/s/articleView?id=campaigns_pardot_alignment_parent.htm&type=5&language=en_US) to use Salesforce Campaigns in Account Engagement. #### Adding Snippets Snippets provide the ability to define a reusable value that can be managed in a central location and used across content. Snippets are great for text that is common and used in multiple locations, like legal language or copyrights. #### Considerations - All Account Engagement customers now require a connected Salesforce org. - The configuration of the customer determines what data is synced between Account Engagement & Salesforce. - Using Account Engagement APIs is ideal for any time-sensitive updates and to avoid concerns related to configuration. ### Custom Email Builder Components Custom components allow the email builder to be extended by developing Lightning Web Components (LWC) modules that can be embedded and configured within the Email Builder Design canvas. Overall, the goal of custom components is to provide marketers with reusable components that accelerate the design of a new email. ### Custom Email Builder Components Example Use Cases #### Integrating Email with an External Service A marketer wants to pull information or content quickly from another source to use within their email. You can create components that: - Pulls in webinar details automatically into an invite email, removing manual copy-paste steps and lowering the risk of introducing errors. - Accesses content that isn't stored in Salesforce by integrating an external CMS. #### Reusable Email Formatting A marketer wants to design an email with advanced components that aren’t provided out of the box. You create components that: - Let marketers easily embed tables in an email, create a data table component. - Makes email building with common patterns quicker with a reusable component that has an image, title, and text. #### References - [Account Engagement Email Builder Extensibility Development Guide](https://developer.salesforce.com/docs/marketing/pardot/builder-extensibility-guide.md) ### Packaged Email Builder Templates The Lightning Email Template builder enables packaging templates and listing them as an app on the AppExchange. Marketers are always looking for ways to boost their campaign effectiveness and a great email design is an easy way to increase prospect engagement. Access to ready-to-use templates allows marketers to quickly ramp up their email marketing programs with high-quality emails. To learn more about this use case, review the [Account Engagement Email Builder Extensibility Development Guide](https://developer.salesforce.com/docs/marketing/pardot/builder-extensibility-guide.md). ### Builder Template Example Use Case Sell a package of Email Builder Templates, containing templates for newsletters, product updates, and events so a new email marketer is able to get started quickly. ### References - [Account Engagement Email Builder Extensibility Development Guide](https://developer.salesforce.com/docs/marketing/pardot/builder-extensibility-guide.md) ## General Salesforce Components Since Account Engagement is available in Salesforce Lightning Experience, consider incorporating Salesforce components into your app. You can create objects to store data, new tabs to create pages for your apps, and many other features. Learn more about [available components](https://developer.salesforce.com/docs/component-library/overview/components). ### General Salesforce Components Example Use Cases #### Configuration Pages Create a configuration page for your app allowing admins to set specific settings and simplify setup. #### Additional Data Object Create an object to store data for your application within Salesforce to surface natively to the marketing team. For example, external activities support minimal information but are possible to provide an extended record for Marketer’s to view more granular details. #### New Marketing Related Service Use Salesforce components to create an app that provides marketing functionality that complements Account Engagement. For example, an app to track and monitor SEO doesn't need direct integration with Account Engagement, but you can expose the app's UI in the Account Engagement Lightning app. ## Getting Started on Development ### Architecture Account Engagement apps typically follow one of these build types: - API-only / Connector - Composite - Native Account Engagement currently supports only First-generation Managed Packaging. ### Environments Partners who are accepted into the Partner Program are given a Partner Business org to manage, sell, and market their apps. ISVs who join the Partner Community can create an Account Engagement Developer org to: - Develop your app - Use a demo environment for security review - Have a demo environment for your sales team to promote your app. To set up an Account Engagement developer org, follow these steps: 1. Join the [Partner Community](https://partnersignup.salesforce.com/)). 2. Join the [Pardot B2B Marketing Automation group](http://p.force.com/pardotgroup). 3. Click the link for “Pardot Dev Org Instructions”, then follow the provided instructions. ### Considerations - The Account Engagement Developer org expires if you don’t have a managed package, or you don’t log in for over a year. - Set up a Salesforce system admin with a monitored email address to receive product impact notifications. - To be included in Account Engagement's product impact notifications, configure Account Engagement Product & Service Notifications in your account settings. - Account Engagement doesn’t support app trial orgs. - Account Engagement doesn’t support scratch orgs and therefore doesn’t support Second-generation Managed Packaging (2GP). However, Custom Builder Components support 2GP as long as they aren’t dependent on any Account Engagement features. - Account Engagement doesn’t support demo orgs via the Environment Hub. ### Partner Onboarding and Potential Costs This high-level overview helps you understand the phases of becoming a partner and when expenses enter into the picture. 1. Join the Partner Community (Free) 2. Start Developing your Application (Free) 3. Prepare Solution Documentation (Free) 4. Sign Partnership Agreement with Salesforce 5. Complete Security Review (Security Review Fees) 6. Publish your AppExchange Listing (Listing Management Fee) Salesforce supports partners by making it free to build and test apps. Salesforce also offers support for developing a business plan and helping you meet your goals for your app. To release an app, partners must become an official Salesforce Partner. During the process, an AppExchange team member consults with you on the partnership agreement. For more information, review the [ISV Onboarding Guide](https://www.salesforce.com/en-us/wp-content/uploads/sites/4/documents/partners/readiness/appexchange_isv_onboarding_guide.pdf). ## General FAQ ### How can I stay up to date on Account Engagement Functionality? - Review the Account Engagement section of the [Salesforce Release Notes](https://help.salesforce.com/s/articleView?id=release-notes.salesforce_release_notes.htm&type=5). - Review the latest [Account Engagement Developer Documentation](https://developer.salesforce.com/docs/marketing/pardot/overview). ### How do I stay aware of changes that can impact my app? - [Sign up](https://partners.salesforce.com/) to receive Partner Alerts. - [Check the Salesforce Feature Retirements](https://help.salesforce.com/s/articleView?id=000313062&type=1) for Account Engagement feature retirements. - An email is sent to the admin of your Account Engagement developer org. Also, be sure to [set up the points of contact](https://help.salesforce.com/s/articleView?id=sf.pardot_admin_product_and_service_notification_overview.htm&type=5) within Account Engagement settings. Ensure you add a monitored email address and ideally for a team so there isn’t a single point of failure. ## Resources This section lists all the resources mentioned in this topic, and additional useful resources: - Partner Resources - Partner Community Resources - [Account Engagement B2B Marketing Community](https://trailblazers.salesforce.com/_ui/core/chatter/groups/GroupProfilePage?g=0F9300000001qUiCAI) - Partner Resources - [Get Started with the AppExchange Partner Program Trailhead module](https://trailhead.salesforce.com/content/learn/modules/isvforce_basics/isvforce_basics_partner_program) - [AppExchange Partner Program Main Site](https://1.appexchange.com/partnerprogram) - [General ISV Onboarding Guide](https://www.appexchangeguides.com/e/isv-onboarding-guide-jcvehuiiqzjsr/slides?hub=partner-community-5e70a5780bf97) - PDO Resources - [PDO Approval Process](http://p.force.com/pdo) - [Navigator Program Details](http://p.force.com/navigator) - Account Engagement Product Resources - [Account Engagement Customer Success Hub](https://www.pardot.com/success/) - [Account Engagement Help Documentation](https://help.salesforce.com/articleView?id=bundle_pardot_parent.htm&type=5) - [All about Account Engagement](https://www.pardot.com/) - [Account Engagement Pricing](https://www.pardot.com/pricing/) - Account Engagement Extensibility Feature Documentation - [Account Engagement API Documentation](https://developer.salesforce.com/) - [Relevant Salesforce API Endpoints for Account Engagement](https://developer.pardot.com/kb/salesforce-endpoints/) - [Marketing Extensibility Features Guide](https://developer.salesforce.com/docs/marketing/pardot/extensibility/extensibility-features-overview.md) - [Builder Extensibility Use Case Guide: Pre-Packaged Templates & Custom Components](https://developer.salesforce.com/docs/marketing/pardot/builder-extensibility-guide.md) - Pardot Certifications - [Pardot Specialist](https://trailhead.salesforce.com/credentials/pardotspecialist) - [Pardot Consultant](https://trailhead.salesforce.com/credentials/pardotconsultant) # Get Started with Account Engagement API Account Engagement’s REST APIs let you access and manipulate your Account Engagement data. - Extend Account Engagement - : Build your own custom integrations to better support your business needs. - Augment Account Engagement Data - : Clean and enrich prospect data, saving your sales reps hours of time spent on menial tasks. - Expand Reporting - : Use the Account Engagement API to automate exporting visitor data to your own external analytics tools for richer insights. - Boost Your Business Value - : Automate tasks, segment prospects with external data, or create custom external scoring models and update prospects. To get answers to your questions about the API, or report a documentation issue, open a ticket with our Support team. [Learn how](https://help.salesforce.com/articleView?id=000181929&type=1). ## Quick Start If you're new to using Account Engagement APIs, see our [Quick Start](https://developer.salesforce.com/docs/marketing/pardot/guide/getting-started.md). ## Account Engagement API Versions Version 5 is the latest iteration of the Account Engagement API, and is the preferred version. ### Version 5 Version 5 provides new functionality. You can use this version whether or not your Account Engagement business unit has "Allow Multiple Prospects with the Same Email Address" enabled. See [Version 5 Overview](/content/en-us/pardot/overviews/pardot-overview.json5) for information about using version 5. ### Versions 3 and 4 If your Account Engagement account has the Allow Multiple Prospects with the Same Email Address (AMPSEA) feature disabled, use version 3 of the Account Engagement API. If your Account Engagement account has AMPSEA enabled, use version 4 of the Account Engagement API. Versions 3 and 4 provide the same functionality, using slightly different input and output syntax to support working with prospects that share an email address. See [Version 3 and 4 Overview](https://developer.salesforce.com/docs/marketing/pardot/guide/version-3-4-overview.md) for information about using versions 3 and 4. ## Test and Production Environments Different Account Engagement environments are hosted on different domains, and you must use the correct domain in your request URLs. In general: - Demos, developer orgs, and sandbox environments are hosted on the domain `pi.demo.pardot.com`. - Training and production environments are hosted on the domain `pi.pardot.com`. You can find the correct URL for your Account Engagement domain from Salesforce Setup. 1. In Salesforce, click the gear icon to access Setup. 2. From Setup, enter **Installed Packages** in the Quick Find box, and then select **Installed Packages**. 3. Find the package **b2bmaIntegration**. - If the namespace prefix is "b2bma", use the domain `pi.pardot.com` in your request URLs. - If the namespace prefix is "pi3", use the domain `pi.demo.pardot.com` in your request URLs. ## Rate Limits We enforce API rate limits in two ways: - daily requests - concurrent requests ### Daily Requests Limits | Account Engagement Edition | Allocated Daily Requests | | -------------------------- | ------------------------ | | Growth | 25,000 | | Plus | 50,000 | | Advanced | 100,000 | | Premium | 100,000 | These limits reset at the beginning of the day based on your account time zone settings. Any request made exceeding the limits result in an [error code 122](https://developer.salesforce.com/docs/marketing/pardot/guide/error-codes.md#error-code-122) You can check your current daily usage on the "usage and limits" page. ### Concurrent Requests To interact with our API more efficiently, you can have up to five concurrent API requests. Any connection over five results in an [error code 66](https://developer.salesforce.com/docs/marketing/pardot/guide/error-codes.md#error-code-66) response. ## Open Source API Wrappers These wrappers aren't officially supported, but are available to use with the Account Engagement API. - [ruby-pardot](https://www.github.com/Pardot/ruby-pardot) - [python-pypardot4](https://github.com/mneedham91/PyPardot4) for version 4 of the API - [pardot-java-client](https://github.com/Crim/pardot-java-client) # Getting Started with the Tracking and Consent JavaScript API **important:** Before you get started, the Tracking and Consent API must be enabled on the account. In Account Engagement: 1. Go to Settings. 2. Click **Edit**. 3. Select **Activate the Tracking & Consent JavaScript API**. In the Account Engagement Lightning App: 1. Select Account Engagement Settings. 2. Click **Edit**. 3. Select **Activate the Tracking & Consent JavaScript API**. To get started, add Account Engagement analytics to your site. This snippet adds Account Engagement analytics to your page and records a page view when the library loads. Replace the `piDomain` with your specific account information. Add the snippet to any page you’d like to collect Account Engagement analytics on. ```javascript ``` Set the `piDomain` to a verified Account Engagement tracker domain in your account. This tracker domain must be a subdomain of the tracked page. For example, adding the snippet to example.com must use a `piDomain` with the root domain of subdomain.example.com. The Account Engagement analytics JavaScript library is loaded asynchronously and establishes an empty analytics action queue if one doesn’t exist. ```javascript (function () { var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "//" + piDomain + "/pdt.js"; var c = document.getElementsByTagName("script")[0]; c.parentNode.insertBefore(s, c); window["pdt"] = window["pdt"] || function () { (window["pdt"].cq = window["pdt"].cq || []).push(arguments); }; })(); ``` Next, add some analytics actions to be processed after the library has loaded. Create an [analytics tracker](https://developer.salesforce.com/docs/marketing/pardot/guide/tracking-and-consent-functions.md#create-tracker), and send a page view to Account Engagement. When a visitor views the page, a tracked page view is sent to Account Engagement. If the page visitor is in a geo that requires consent as defined in your Account Engagement account settings and hasn’t yet opted in, the page view isn't recorded. Instead, the consent banner is shown. ```javascript // Create an analytics tracker with the required information: // pdt('create', Account Engagement account ID + 1000, Account Engagement campaign ID + 1000, 'go.example.com'); pdt("create", 0001, 0002, piDomain); pdt("sendPageView"); ``` Analytics actions are always processed in order after the Account Engagement analytics library has loaded. Additional actions are processed synchronously after the queue has been processed. See [Tracking and Consent Functions](https://developer.salesforce.com/docs/marketing/pardot/guide/tracking-and-consent-functions.md) for additional actions you can take with Account Engagement analytics. # Marketing App Extensions Set up the metadata for extensions and activity types. ## Endpoints and Parameters Use these endpoints to set up an extension. | Endpoint | Description | | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `MarketingAppExtension` | The metadata that defines the third-party application. | | `MarketingAppExtensionAssignment` | The relationship between the extension and a business unit. This object determines which business unit to pass data to and from. | | `PardotTenant` | The metadata for the business unit. Use this endpoint to identify when you create a MarketingAppExtensionAssignment. | ## Create the Marketing App Extension Set up an extension to represent a third-party app. In this example, we set up a webinar extension and assign it to the HappyHomeTX business unit. 1. Authenticate to the Salesforce API. 2. Make a request to create an extension for a webinar service and set IsActive to true. We recommend naming it after the service to make it easy to recognize the source. Here is an example request. ``` POST /services/data/v55.0/tooling/objects/MarketingAppExtension HTTP/1.1 Host: YOUR_DOMAIN Authorization: Bearer YOUR_ACCESS_TOKEN Content-Type: application/json Cookie: YOUR_COOKIE_ID CookieConsentPolicy=0:0 Content-Length: 123 { "DeveloperName": "VidYard", "MasterLabel": "VidYard", "Description": "Extension for Webinar", "IsActive": "true" } ``` Response: ``` { "id": "01987654321098MAA", "success": true, "errors": [], "warnings": [], "infos": [] } ``` ## Assign the Extension to a Business Unit Next, assign the extension to the business unit you want to pass data to or from. This step is required even if you have only one business unit. 1. Use query to find your PardotTenant ID. This value is your business unit ID. You can also find this ID in Setup under Business Unit Setup. ``` GET /services/data/v55.0/tooling/query?q=select+id,PardotTenantName+from+PardotTenant HTTP/1.1 Host: YOUR_DOMAIN Authorization: Bearer YOUR_ACCESS_TOKEN Cookie: YOUR_COOKIE_ID CookieConsentPolicy=0:0 ``` The response includes IDs for all of the business units in your accounts. ```json { "size": 3, "totalSize": 3, "done": true, "queryLocator": null, "entityTypeName": "PardotTenant", "records": [ { "attributes": { "type": "PardotTenant", "url": "/services/data/v55.0/tooling/objects/PardotTenant/01234567890123KAM" }, "Id": "01234567890123KAM", "PardotTenantName": "HappyHomeCA" }, { "attributes": { "type": "PardotTenant", "url": "/services/data/v55.0/tooling/objects/PardotTenant/01234567890123KAP" }, "Id": "01234567890123KAP", "PardotTenantName": "HappyHomeTX" }, { "attributes": { "type": "PardotTenant", "url": "/services/data/v55.0/tooling/objects/PardotTenant/01234567890123KAE" }, "Id": "01234567890123KAE", "PardotTenantName": "HappyHomePA" } ] } ``` 2. To assign the extension, send a POST request to the `/tooling/objects/MarketingAppExtAssignment` endpoint. In the request body, include the tenant ID as the value of the `ParentId` property, and the app ID as the value of the `MarketingAppExtensionId` property. ``` POST /services/data/v55.0/tooling/objects/MarketingAppExtAssignment HTTP/1.1 Host: YOUR_DOMAIN Authorization: Bearer YOUR_ACCESS_TOKEN Content-Type: application/json Cookie: YOUR_COOKIE_ID CookieConsentPolicy=0:0 Content-Length: 84 { "ParentId": "01234567890123KAM", "MarketingAppExtensionId" : "01987654321098MAA" } ``` A successful request returns a `201 Created` response. # Object Field References - Requests `create`, `update`, and `upsert` manipulate fields marked as 'Editable'. - 'Required' means that the specified field can't be left without a value during `insert` and some `upsert` requests. Account Engagement declines any `update` request that clears a required field. - During `update` requests, unless otherwise specified the parameter names submitted to the API and tag names in the API's response match field names within the Account Engagement user interface. ## Account | Field Name | Data Type | Required | Editable | Description | | ---------------------------- | --------- | -------- | -------- | ---------------------------------------------- | | **`id`** | integer | | | Account Engagement ID for this account. | | **`level`** | string | | | The level of product for the account. | | **`website`** | string | | | Account website. | | **`vanity_domain`** | string | | | Custom vanity domain name. | | **`plugin_campaign_id`** | integer | | | Plugin ID for account campaign. | | **`tracking_code_template`** | string | | | Markup and code for use in tracking templates. | | **`address1`** | string | | | Account contact address, line 1. | | **`address2`** | string | | | Account contact address, line 2. | | **`city`** | string | | | Account contact city. | | **`state`** | string | | | Account contact state. | | **`territory`** | string | | | Account contact territory. | | **`zip`** | integer | | | Account contact ZIP code. | | **`country`** | string | | | Account contact country (full string). | | **`phone`** | string | | | Account contact phone number. | | **`fax`** | string | | | Account contact fax number. | ## Campaign | Field Name | Data Type | Required | Editable | Description | | ---------- | --------- | -------- | -------- | ---------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this campaign. | | **`name`** | string | | X | Campaign's name. | | **`cost`** | integer | | X | Cost related to the campaign. | ## Custom Field | Field Name | Data Type | Required | Editable | Description | | ---------------------------------- | --------- | -------- | -------- | ------------------------------------------------------------------------------------------------------ | | **`id`** | integer | X | | Account Engagement ID for this custom field. | | **`name`** | string | | X | Custom field's name. | | **`field_id`** | string | | | API ID for custom field | | **`type`** | string | | X | Type of field. | | **`type_id`** | integer | | | Account Engagement ID for custom field's type. | | **`created_at`** | timestamp | | | Time custom field is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time custom field was updated. Time is reported in API user's preferred timezone. | | **`is_record_multiple_responses`** | boolean | | X | If true, this custom field records multiple responses. | | **`crm_id`** | string | | X | The CRM ID of the field you want to map to this custom field. | | **`is_use_values`** | boolean | | X | If true, this custom field uses predefined values. | | **`is_analytics_synced`** | boolean | | | If true, this custom field is marked to sync with Tableau CRM. | ## Custom Redirect | Field Name | Data Type | Required | Editable | Description | | ----------------- | --------- | -------- | -------- | --------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this custom redirect. | | **`name`** | string | | | Custom redirect's name. | | **`Url`** | string | | | URL for the custom redirect. | | **`destination`** | string | | | URL the custom redirect leads to | | **`campaign`** | string | | | The campaign associated with this custom redirect. | | **`created_at`** | timestamp | | | Time custom redirect is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time custom redirect was updated. Time is reported in API user's preferred timezone. | ## Dynamic Content | Field Name | Data Type | Required | Editable | Description | | ----------------- | --------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this dynamic content. | | **`name`** | string | | | Dynamic content's name. | | **`embedCode`** | string | | | Code to embed this dynamic content onto your webpage. | | **`embedUrl`** | string | | | URL to embed this dynamic content. | | **`baseContent`** | string | | | The default dynamic content. | | **`basedOn`** | string | | | Field that this dynamic content is based on. | | **`variation`** | node | | | The variation of content that the prospect sees based on the field's value. **Note:** Information about a variation is returned in a `` node in the XML response. It contains the value of the field in the `` tag and the content of the variation in the `` tag. | | **`created_at`** | timestamp | | | Time dynamic content is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time dynamic content was updated. Time is reported in API user's preferred timezone. | ## Email | Field Name | Data Type | Required | Editable | Description | | ---------------- | ---------- | -------- | -------- | ----------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this email. | | **`name`** | string | | | Name of this email. | | **`subject`** | string | | | Email subject. | | **`message`** | XML Object | | | Contains text and html elements of different formats. | | **`created_at`** | Timestamp | | | Time the email is created. | ## Email Clicks | Field Name | Data Type | Required | Editable | Description | | ---------------------------- | --------- | -------- | -------- | ---------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this email click. | | **`prospect_id`** | integer | | | Account Engagement ID for the associated prospect. | | **`url`** | string | | | URL of the email click. | | **`list_email_id`** | integer | | | Account Engagement ID for the associated list email. Value not present if null. | | **`drip_program_action_id`** | integer | | | Account Engagement ID for the associated drip program action. Value not present if null. | | **`email_template_id`** | integer | | | Account Engagement ID for the associated email template. Value not present if null. | | **`tracker_redirect_id`** | integer | | | Account Engagement ID for the associated tracker redirect. Value not present if null. | | **`created_at`** | timestamp | | | Time that email click occurs. Time is reported in API user's preferred timezone. | ## Form | Field Name | Data Type | Required | Editable | Description | | ----------------- | --------- | -------- | -------- | ---------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this form. | | **`name`** | string | | | Form's name. | | **`campaign_id`** | string | | | Account Engagement ID of the campaign associated with this form. | | **`embed_code`** | string | | | The code used to embed the form on your webpage. | | **`created_at`** | timestamp | | | Time form is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time form was updated. Time is reported in API user's preferred timezone. | ## Identified Company | Field Name | Data Type | Required | Editable | Description | | -------------------- | --------- | -------- | -------- | -------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this identified company. | | **`name`** | string | | | Identified Company's name. | | **`street_address`** | string | | | Identified Company's street address. | | **`city`** | string | | | Identified Company's city. | | **`state`** | string | | | Identified Company's state. | | **`postal_code`** | string | | | Identified Company's postal code. | | **`country`** | string | | | Identified Company's country. | | **`email`** | string | | | Identified Company's email address. | ## Lifecycle History | Field Name | Data Type | Required | Editable | Description | | ----------------------- | --------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID of this lifecycle history. | | **`prospect_id`** | integer | | | Account Engagement ID for the prospect in this stage. | | **`previous_stage_id`** | integer | | | Account Engagement ID of the stage this prospect previously was in. | | **`next_stage_id`** | integer | | | Account Engagement ID of the stage this prospect is in next. | | **`seconds_elapsed`** | integer | | | Number of seconds for prospect to get to current stage. | | **`created_at`** | timestamp | | | Time lifecycle history is created in Account Engagement. Time is reported in API user's preferred timezone. | ## Lifecycle Stage | Field Name | Data Type | Required | Editable | Description | | --------------- | --------- | -------- | -------- | ---------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID of this lifecycle stage. | | **`name`** | string | | | Lifecycle stage's name. | | **`position`** | integer | | | Lifecycle stage's position in lifecycle. | | **`is_locked`** | boolean | | | If true, lifecycle stage is locked. | ## List | Field Name | Data Type | Required | Editable | Description | | -------------------- | --------- | -------- | -------- | ---------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID of this list. | | **`name`** | string | | X | List's name (internal to Account Engagement). | | **`is_public`** | boolean | | X | If true, list shows on EPC pages to prospects. | | **`is_dynamic`** | boolean | | | If true, list has prospects dynamically added to it via a set of chosen rules. | | **`title`** | string | | X | List's title (visible to subscribers) | | **`description`** | string | | X | List's description. | | **`is_crm_visible`** | boolean | | X | If true, list is visible in CRM, and can be added to, or removed from. | | **`created_at`** | timestamp | | | Time list is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time list was updated. Time is reported in API user's preferred timezone. | ## List Membership | Field Name | Data Type | Required | Editable | Description | | ----------------- | --------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this list membership. | | **`list_id`** | integer | X | | Account Engagement ID of the list for this membership. | | **`prospect_id`** | integer | X | | Account Engagement ID of the prospect for this membership. | | **`opted_out`** | integer | | X | If value is 1, the prospect is unsubscribed from receiving emails from this list. | | **`created_at`** | timestamp | | | Time that this membership is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time that this membership was updated. Time is reported in API user's preferred timezone. | ### Additional prospect fields available for Export When using the [v3 Export API](https://developer.salesforce.com/docs/marketing/pardot/guide/v3/export-v3.md#list-membership) or [v4 Export API](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/export-v4.md#list-membership) to export list membership, the following fields are selectable for export in addition to the [list membership fields](#list-membership) listed above. **Note**: The following fields are only available via the Export API and are only exported if selected via `fields` parameter specified in export `create` request. | Field Name | Data Type | Description | | ---------------- | --------- | ---------------------------------------------------------------- | | **`created_by`** | integer | Account Engagement ID for the user who created this object. | | **`updated_by`** | integer | Account Engagement ID for the user who last updated this object. | ## Opportunity | Field Name | Data Type | Required | Editable | Description | | ----------------- | --------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **`id`** | integer | X | | Account Engagement ID for this opportunity. | | **`campaign_id`** | integer | X | X | Account Engagement ID of the campaign associated with this opportunity.
  • **Note**: Information about an opportunity's campaign association is returned in a `` node in the XML response. However, updates to campaign associations are made by providing campaign_id=`` during an `` request. See [XML Response](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/opportunities-v4.md#xml-response) in the Campaign documentation for more details.
| | **`name`** | string | X | X | Opportunity's name | | **`value`** | float | X | X | Opportunity's value.
  • **Restrictions**: The value must be a positive numeric value.
| | **`probability`** | integer | X | X | Opportunity's probability.
  • **Restrictions**: The value must be a positive integer from 0 through 100, inclusive.
| | **`type`** | string | | X | Opportunity's type. | | **`stage`** | string | | X | Opportunity's stage. | | **`status`** | string | | X | Opportunity's status.
  • **Restrictions**: status must be either won, lost, or open.
| | **`closed_at`** | timestamp | | X | Opportunity's closed date.
  • **Note** If this field is left blank, the closed_at timestamp (Closed Date within the app) is not set, even when the Opportunity's stage, status, or probability are set to indicate opportunity closure.
| | **`created_at`** | timestamp | | | Time opportunity is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time opportunity was updated in Account Engagement. Time is reported in the API user's preferred timezone. | ## Profile | Field Name | Data Type | Required | Editable | Description | | ---------- | --------- | -------- | -------- | --------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this profile. | | **`name`** | string | | | Profile's name. | ## Profile Criteria | Field Name | Data Type | Required | Editable | Description | | ------------- | --------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Required. Account Engagement ID for this profile criteria. | | **`name`** | string | | | Profile criteria's name. | | **`matches`** | string | | X | The matching status of this profile criteria with the current prospect.
  • **Restrictions:** Updates can be performed by using the values `match`, `nomatch`, or `unknown`.
| ## Prospect | Field Name | Data Type | Required | Editable | Description | | ------------------------- | --------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this prospect. | | **`campaign_id`** | integer | | X | Account Engagement ID of the campaign associated with this prospect
  • **Note**: Information about a prospect's campaign association is returned in a `` node in the XML response. However, updates to campaign associations are made by providing campaign_id=`` during an `` request. See [XML Response Formats](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md#xml-response-format) in [Prospects](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md) for more details.
| | **`salutation`** | string | | X | Prospect's formal prefix. | | **`first_name`** | string | | X | Prospect's first name. | | **`last_name`** | string | | X | Prospect's last name. | | **`email`** | string | X | X | Prospect's email address. | | **`password`** | string | | X | Prospect's password. | | **`company`** | string | | X | Prospect's company. | | **`prospect_account_id`** | integer | | X | Prospect's account ID. | | **`website`** | string | | X | Prospect's website URL. | | **`job_title`** | string | | X | Prospect's job title. | | **`department`** | string | | X | Prospect's department. | | **`country`** | string | | X | Prospect's country. | | **`address_one`** | string | | X | Prospect's address, line 1. | | **`address_two`** | string | | X | Prospect's address, line 2. | | **`city`** | string | | X | Prospect's city. | | **`state`** | string | | X | Prospect's US state. | | **`territory`** | string | | X | Prospect's territory. | | **`zip`** | string | | X | Prospect's postal code. | | **`phone`** | string | | X | Prospect's phone number. | | **`fax`** | string | | X | Prospect's fax number. | | **`source`** | string | | X | Prospect's source. | | **`annual_revenue`** | string | | X | Prospect's annual revenue. | | **`employees`** | string | | X | Prospect's number of employees. | | **`industry`** | string | | X | Prospect's industry. | | **`years_in_business`** | string | | X | Prospect's number of years in business. | | **`comments`** | string | | X | Comments about this prospect. | | **`notes`** | string | | X | Notes about this prospect
  • **Note**: Available for export, but only exported if selected via `fields` parameter specified in export `create` request.
| | **`score`** | integer | | X | Prospect's score. | | **`grade`** | string | | | Prospect's letter grade
  • **Note**: Available for export, but only exported if selected via `fields` parameter specified in export `create` request.
| | **`last_activity_at`** | timestamp | | | Time stamp of this prospect's latest visitor activity; Time is reported in API user's preferred timezone. | | **`recent_interaction`** | string | | | Describes the prospect's most recent interaction with Account Engagement **(Not available for V3/V4 export)**. | | **`crm_lead_fid`** | string | | | Prospect's lead ID in a supported CRM system. | | **`crm_contact_fid`** | string | | | Prospect's contact ID in a supported CRM system. | | **`crm_owner_fid`** | string | | | Prospect's owner ID in a supported CRM system. | | **`crm_account_fid`** | string | | | Account ID in a supported CRM system. | | **`crm_last_sync`** | timestamp | | | Last time this prospect was synced with a supported CRM system. | | **`crm_url`** | string | | | URL to view the prospect within the CRM system **(Not available for V3/V4 export)**. | | **`is_do_not_email`** | boolean | | X | If value is 1, prospect prefers not to be emailed. | | **`is_do_not_call`** | boolean | | X | If value is 1, prospect prefers not to be called. | | **`opted_out`** | boolean | | | If value is 1, prospect has opted out of marketing communications. | | **`is_reviewed`** | boolean | | X | If value is 1, prospect has been reviewed. | | **`is_starred`** | boolean | | X | If value is 1, prospect has been starred. | | **`is_archived`** | boolean | | X | If value is 1, prospect has been archived. | | **`created_at`** | timestamp | | | Time prospect is created in Account Engagement; Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time prospect was updated in Account Engagement; Time is reported in API user's preferred timezone. | ### Additional prospect fields available for Export When using the [v3 Export API](https://developer.salesforce.com/docs/marketing/pardot/guide/v3/export-v3.md#prospect) or [v4 Export API](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/export-v4.md#prospect) to export prospects, the following prospect fields are selectable for export in addition to the [prospect fields](#prospect) listed above. **Note**: The following fields are only available via the Export API and are only exported if selected via `fields` parameter specified in export `create` request. | Field Name | Data Type | Description | | -------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`converted_at`** | timestamp | Time when prospect was converted from visitor; Time is reported in API user's preferred timezone | | **`converted_from_object_type`** | string | Type of object associated with visitor activity that resulted in prospect being converted from visitor. Supported values include 'Form', 'FormHandler', 'LandingPage', 'MultivariateTestVariation', and 'Video'. | | **`converted_from_object_name`** | string | Name of object associated with visitor activity that resulted in prospect being converted from visitor. | | **`do_not_sell`** | boolean | Indicates whether the visitor recorded an activity with the Global Privacy Control Header enabled. | | **`is_email_hard_bounced`** | boolean | if value is 1, prospect email address has hard bounced. | | **`email_bounced_at`** | timestamp | Time when prospect email address hard bounced; Time is reported in API user's preferred timezone. | | **`email_bounced_reason`** | string | Reason why prospect email address hard bounced. | | **`first_assigned_at`** | timestamp | Time prospect was first assigned to a user; Time is reported in API user's preferred timezone. | | **`first_activity_at`** | timestamp | Time when first visitor activity occurred for this prospect; Time is reported in API user's preferred timezone. | | **`first_referrer_url`** | string | First referrer's URL. | | **`first_referrer_type`** | string | First referrer's vendor and type (such as 'Google Natural Search'). | | **`first_referrer_query`** | string | First referrer's search query. | | **`campaign_parameter`** | string | Prospect's campaign parameter utm_campaign from Google Analytics. | | **`medium_parameter`** | string | Prospect's medium parameter utm_medium from Google Analytics. | | **`source_parameter`** | string | Prospect's source parameter utm_source from Google Analytics. | | **`content_parameter`** | string | Prospect's content parameter utm_content from Google Analytics. | | **`term_parameter`** | string | Prospect's term parameter utm_term from Google Analytics. | | **`created_by`** | integer | Account Engagement ID for the user who created this object. | | **`updated_by`** | integer | Account Engagement ID for the user who last updated this object. | ## Prospect Account **Note:** Prospect account fields are fully customizable. To get the most accurate field metadata for your Account Engagement business unit, use the describe operation on the prospectAccount API endpoint. | Field Name | Data Type | Required | Editable | Description | | ---------- | --------- | -------- | -------- | ---------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID of the prospect account. | | **`name`** | string | X | | The name of the prospect account. | ### Additional prospect account fields available for Export When using the [v3 Export API](https://developer.salesforce.com/docs/marketing/pardot/guide/v3/export-v3.md#prospect-account) or [v4 Export API](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/export-v4.md#prospect-account) to export prospect account, the following fields are selectable for export in addition to the [prospect account fields](#prospect-account) listed above. **Note**: The following fields are only available via the Export API and are only exported if selected via `fields` parameter specified in export `create` request. | Field Name | Data Type | Description | | ---------------- | --------- | ---------------------------------------------------------------- | | **`created_by`** | integer | Account Engagement ID for the user who created this object. | | **`updated_by`** | integer | Account Engagement ID for the user who last updated this object. | ## Tag | Field Name | Data Type | Required | Editable | Description | | ---------------- | --------- | -------- | -------- | --------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this tag. | | **`name`** | string | | | Tag's name. | | **`created_at`** | timestamp | | | Time tag is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time tag was updated. Time is reported in API user's preferred timezone. | ## Tag Object | Field Name | Data Type | Required | Editable | Description | | ---------------- | --------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID of the tag object. | | **`tag_id`** | integer | | | The Account Engagement ID of the tag. | | **`type`** | string | | | The type of object associated with the tag. | | **`object_id`** | integer | | | The Account Engagement ID of the object. | | **`created_at`** | timestamp | | | Time tag is associated with the object in Account Engagement. Time is reported in API user's preferred timezone. | ## User | Field Name | Data Type | Required | Editable | Description | | ---------------- | --------- | -------- | -------- | -------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID of the user. | | **`email`** | string | | | User's email address. | | **`first_name`** | string | | | User's first name. | | **`last_name`** | string | | | User's last name. | | **`job_title`** | string | | | User's job title | | **`role`** | string | | | User's role. | | **`created_at`** | timestamp | | | Time user is created in Account Engagement. Time is reported in the API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time user was updated in Account Engagement. Time is reported in the API user's preferred timezone. | ## Visit | Field Name | Data Type | Required | Editable | Description | | -------------------------------- | --------- | -------- | -------- | ----------------------------------------------------------------------------------------------------- | | **`id`** | integer | | | Account Engagement ID for this visit. | | **`visitor_id`** | integer | | | Account Engagement ID for the associated visitor. | | **`prospect_id`** | integer | | | Account Engagement ID for the associated prospect. | | **`visitor_page_view_count`** | integer | | | Number of page views for this visit. | | **`first_visitor_page_view_at`** | timestamp | | | Time of first page view for this visit. Time is reported in API user's preferred timezone | | **`last_visitor_page_view_at`** | timestamp | | | Time of last page view for this visit. Time is reported in API user's preferred timezone. | | **`duration_in_seconds`** | integer | | | Length of this visit. | | **`campaign_parameter`** | string | | | Visit's campaign parameter utm_campaign from Google Analytics. | | **`medium_parameter`** | string | | | Visit's medium parameter utm_medium from Google Analytics. | | **`source_parameter`** | string | | | Visit's source parameter utm_source from Google Analytics. | | **`content_parameter`** | string | | | Visit's content parameter utm_content from Google Analytics. | | **`term_parameter`** | string | | | Visit's term parameter utm_term from Google Analytics. | | **`created_at`** | timestamp | | | Time visit is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time visit was updated in Account Engagement. Time is reported in API user's preferred timezone. | ## Visitor | Field Name | Data Type | Required | Editable | Description | | ------------------------ | --------- | -------- | -------- | ------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this visitor. | | **`page_view_count`** | integer | | | Number of page views by this visitor. | | **`ip_address`** | string | | | Visitor's IP address. | | **`hostname`** | string | | | Visitor's hostname. | | **`campaign_parameter`** | string | | | Visitor's campaign parameter utm_campaign from Google Analytics | | **`medium_parameter`** | string | | | Visitor's medium parameter utm_medium from Google Analytics. | | **`source_parameter`** | string | | | Visitor's source parameter utm_source from Google Analytics. | | **`content_parameter`** | string | | | Visitor's content parameter utm_content from Google Analytics | | **`term_parameter`** | string | | | Visitor's term parameter utm_term from Google Analytics. | | **`created_at`** | timestamp | | | Time visitor is created in Account Engagement. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Last time visitor was updated in Account Engagement. Time is reported in API user's preferred timezone. | ## Additional Visitor Fields Available for Export When using either the [v3 Export API](https://developer.salesforce.com/docs/marketing/pardot/guide/v3/export-v3.md) or the [v4 Export API](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/export-v4.md) to export visitors, the following prospect fields are selectable for export in addition to the [Visitor fields](#visitor) listed earlier. | Field Name | Data Type | Description | | ----------------- | --------- | -------------------------------------------------------------------------------------------------- | | **`do_not_sell`** | boolean | Indicates whether the visitor recorded an activity with the Global Privacy Control Header enabled. | ## Visitor Activity | Field Name | Data Type | Required | Editable | Description | | ------------------------------------ | --------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`id`** | integer | X | | Account Engagement ID for this visitor activity | | **`prospect_id`** | integer | | | Account Engagement ID for the associated prospect | | **`visitor_id`** | integer | | | Account Engagement ID for the associated visitor | | **`type`** | integer | | | Visitor activity's type number. See the [listing that follows](#visitor-activity-types). | | **`type_name`** | string | | | Visitor activity's type name. See the [listing that follows](#visitor-activity-types). | | **`details`** | string | | | Details about this visitor activity. Examples include
  • The name of the object associated with this activity.
  • The search phrase used in a site search query.
  • Others as your needs require.
| | **`email_id`** | integer | | | Account Engagement ID of the email associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has an email associated with it.
| | **`email_template_id`** | integer | | | Account Engagement ID of the email template associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has an email associated with it.
| | **`list_email_id`** | integer | | | Account Engagement ID of the list email associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has an email associated with it.
| | **`form_id`** | integer | | | Account Engagement ID of the form associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has a form associated with it.
| | **`form_handler_id`** | integer | | | Account Engagement ID of the form handler associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has a form handler associated with it.
| | **`site_search_query_id`** | integer | | | Account Engagement ID of the site search query associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has a site search query associated with it.
| | **`landing_page_id`** | integer | | | Account Engagement ID of the landing page associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has a landing page associated with it.
| | **`paid_search_ad_id`** | integer | | | Account Engagement ID of the paid search ad associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has a paid search ad associated with it.
| | **`multivariate_test_variation_id`** | integer | | | Account Engagement ID of the multivariate test variation associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has a multivariate test variation associated with it.
| | **`file_id`** | integer | | | Account Engagement ID of the file associated with this visitor activity.
  • **Note:** This node appears only if this visitor activity has a file associated with it.
| | **`custom_redirect_id`** | integer | | | Account Engagement ID of the custom redirect associated with this visitor activity. **Note:** This node appears only if this visitor activity has a custom redirect associated with it. | | **`campaign`** | object | | | Campaign information including id, name, and cost. **(Not available for V3/V4 export)**. | | **`created_at`** | timestamp | | | Time that visitor activity occurred. Time is reported in API user's preferred timezone. | | **`updated_at`** | timestamp | | | Time that visitor activity update occurred. Time is reported in API user's preferred timezone. | ### Visitor Activity Types Visitor Activities have the following values for `type`. - 1 - Click - 2 - View - 3 - Error - 4 - Success - 5 - Session (Omitted from Synchronous and Export endpoints) - 6 - Sent - 7 - Search - 8 - New Opportunity - 9 - Opportunity Won - 10 - Opportunity Lost - 11 - Open - 12 - Unsubscribe Page - 13 - Bounced - 14 - Spam Complaint - 15 - Email Preference Page - 16 - Resubscribed - 17 - Click (Third Party) - 18 - Opportunity Reopened - 19 - Opportunity Linked - 20 - Visit - 21 - Custom URL click - 22 - Olark Chat - 23 - Invited to Webinar - 24 - Attended Webinar - 25 - Registered for Webinar - 26 - Social Post Click - 27 - Video View - 28 - Event Registered - 29 - Event Checked In - 30 - Video Conversion - 31 - UserVoice Suggestion - 32 - UserVoice Comment - 33 - UserVoice Ticket - 34 - Video Watched (≥ 75% watched) - 35 - Indirect Unsubscribe Open - 36 - Indirect Bounce - 37 - Indirect Resubscribed - 38 - Opportunity Unlinked - Other - Unknown ## Visitor Page View | Field Name | Data Type | Required | Editable | Description | | ---------------- | --------- | -------- | -------- | --------------------------------------------------------------------------- | | **`id`** | integer | | | Account Engagement ID for this visitor page view. | | **`url`** | string | | | Page view. URL | | **`title`** | string | | | Page title. | | **`created_at`** | timestamp | | | Time page view occurred. Time is reported in API user's preferred timezone. | ## Visitor Referrer | Field Name | Data Type | Required | Editable | Description | | -------------- | --------- | -------- | -------- | ------------------------------------------------ | | **`id`** | integer | X | | Account Engagement ID for this visitor referrer. | | **`referrer`** | string | | | Referrer's URL. | | **`vendor`** | string | | | Referrer's vendor (such as 'Google' or 'Yahoo'). | | **`type`** | string | | | Referrer's type (such as 'Natural Search'). | | **`query`** | string | | | Referrer's search query. | # PardotTenant Tooling API Reference This [Tooling API](https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/intro_api_tooling.htm) object represents an Account Engagement business unit. It’s available in API version 56.0 and later. - Queue a new account or business unit with the SOAP operation `create()`, or with the REST HTTP verb `POST`. - Query an existing account or business unit with the SOAP operations `query()`, and `retrieve()`, or with the REST HTTP verb `GET`. - Update an existing account or business unit with the SOAP operation `update()`, or with the REST HTTP verb `PATCH`. ## Supported Soap Calls - `create()` - `query()` - `retrieve()` - `update()` ## Supported REST HTTP Methods - `GET` - `PATCH` - `POST` ## Fields | Field Name | Type | Description | | ---------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | CreationStatus | string | The operational status of the Account Engagement business unit. | | InitialPardotAdminId | reference | A reference to the Salesforce User ID associated with this Account Engagement business unit. | | PardotTenantId | string | The id of the Account Engagement business unit for this record. | | PardotTenantName | string | The name of the Account Engagement business unit. | | PardotTenantStatusCode | string | Metadata about the operational status of the Account Engagement business unit. The possible values are
  • `InsufficientLicenseLimits`
  • `InvalidRequest`
  • `PardotAccountNotFound`
  • `UnknownError`
  • `UsernameCollision`
| ## Create a PardotTenant Queue the creation of a PardotTenant record by setting: 1. A valid User ID as the value for the field `InitialPardotAdminId`. 2. A unique value for `PardotTenantName`, if your organization supports multiple Account Engagement business units. ## Verify the Status of a PardotTenant To find the status of an Account Engagement business unit after its creation has been queued, query the account for a given ID. A value of `CREATING` in `CreationStatus` indicates that the creation process is in progress. A value of `CREATED` in `CreationStatus` indicates that the creation process is finished. ## Update a PardotTenant Under limited circumstances, updates are allowed to a PardotTenant record. - Any change to the `PardotTenantName` field, which doubles as the company name of your business unit. - Removing a PardotTenant in an error state. To do so, change the `CreationStatus` of the record to `DELETED`. One of the following must be true: - The PardotTenant record has a value of `ERROR` for `CreationStatus`. - The PardotTenant record has a value of `CREATING`, `UPDATING`, or `DELETING` for `CreationStatus`, and isn't modified within the past hour. ## Delete a PardotTenant Outside the error state described in [Update a PardotTenant](#update-a-pardottenant), deleting a PardotTenant isn’t supported. ## Error Messages | Error Message | Description | | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `No Id on record to update` | You didn’t provide the Id field in the request payload, so we can’t update a specific record. | | `Attempted record update is not for a PardotTenant` | The attempted record update isn’t for a PardotTenant. | | `Could not find record to update for given Id` | No record with the given ID could be found for update. | | `Record was not in error state before attempted deletion` | The record wasn’t in an error state before the attempted deletion. You can only delete a record that has a value of `Error` for `CreationStatus`. | | `Record has a PardotTenantId configured and can not be deleted` | The record has a `PardotTenantId` configured and can't be deleted. | # Salesforce Objects for Account Engagement Development These Salesforce objects relate to Account Engagement, and can come in handy when building solutions with Account Engagement APIs. ## Account - Represents an individual account, which is an organization or person involved with your business (such as customers, competitors, and partners). - Salesforce Account is the primary object for account information, and is synced to Account Engagement Prospect Accounts. - The Account Engagement Prospect Account object is read-only. Useful to link Salesforce Accounts to Account Engagement Prospect IDs. Learn more about the account object in the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_account.htm). ## Campaign - Represents and tracks a marketing campaign, such as a direct mail promotion, webinar, or trade show. - After Connected Campaigns are turned on, the Salesforce campaign object becomes the primary campaign object, and its information is synced to Account Engagement Campaigns. - After Connected Campaigns are turned on, the Account Engagement Campaigns endpoint becomes read only. Useful to link Account Engagement Campaign IDs used for Account Engagement records to Salesforce Campaign IDs. Learn more about the campaign object in the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_campaign.htm). ## Campaign Influence - Campaign Influence helps you attribute a percentage of success to influential campaigns. - Use Campaign Influence to manage how marketing attribution is allocated to each campaign. Learn more about the Campaign Influence object the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_campaigninfluence.htm). ## Campaign Influence Model - This read-only object represents a campaign influence model in Customizable Campaign Influence. Use campaign influence models to group CampaignInfluence records created by a specific set of triggers and workflows that you define. Learn more about the Campaign Influence Model object in the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_campaigninfluencemodel.htm). ## Campaign Status - One or more member status values defined for a campaign. Learn more about the campaign status object in the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_campaignmemberstatus.htm). ## Campaign Member - Represents the association between a campaign and either a lead or a contact. Learn more about the campaign member object in the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_campaignmember.htm). ## Lead - Represents a prospect or lead. - Account Engagement can bi-directionally sync Prospect information with Salesforce Lead records. Learn more about the lead object in the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_lead.htm). ## Contact - Represents a contact, which is a person associated with an account. - Account Engagement can bi-directionally sync Prospect records with contact records. Learn more about the contact object in [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contact.htm). ## Email Content Email Content: - Represents a marketing email asset for use with Account Engagement. This object is available in API version 50.0 and later. - Email content is the email record used in the send experience in the new Email Lightning Experience. Learn more about the email content object in the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_emailcontent.htm). ## Snippets - Represents a snippet, which is a container for rich text that can be reused across Account Engagement emails and email templates. This object is available in API version 47.0 and later. - Snippets can be used as an HML variable tag in Account Engagement Assets. Learn more about the snippets object in the [Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_snippet.htm). # Tracking and Consent API Overview The Tracking & Consent API provides functions for each step in the page view tracking process, giving you unparalleled control over how Account Engagement tracks page views. Use the API to implement your own solutions that cover your compliance needs and use cases. ![An image that represents the 4 basic steps used in the tracking and consent API](https://developer.salesforce.com/media/pardot/tac-overview.png) To use the API: 1. Retrieve the JavaScript file. The file includes the functions available in the Tracking and Consent JavaScript API. 2. Initialize a queue. The queue makes sure that commands are executed sequentially. 3. Configure the Tracker Data object. The object lets you set parameters for the activity and pass information between commands. 4. Execute custom tracking logic. Execute your logic using the Tracking and Consent API functions. See [Getting Started with the Tracking and Consent JavaScript API](https://developer.salesforce.com/docs/marketing/pardot/guide/tracking-and-consent-getting-started.html). # Tracking and Consent Functions The Tracking and Consent API supports these functions. ## Standard Functions ### Create Tracker `create ( piAId, piCId, tracker domain hostname)` Creates the Account Engagement tracker necessary for analytics. Add 1000 to the Account Engagement instance ID (`piAId`) and the campaign ID (`piCId`). Example ```javascript pdt(‘create', 0001, 0002, ‘go.example.com’); ``` ### Set Tracked Properties `set( propertyName, value)` **Return**: undefined Updates the value of a tracked property. Subsequent page views sent to Account Engagement include the updated property value. See [Writeable Analytics Parameters](#writeable-analytics-parameters) for the properties that support updates. Example ```javascript pdt("set", "title", "About Us"); ``` ### Send Page View `sendPageView()` **Return**: undefined Sends a page view to Account Engagement that includes the current values of Tracker object properties. If the value of the `pi_opt_in` cookie is false, then no request is made. Example ```javascript pdt("sendPageView"); ``` ## Consent Functions ### Show Consent Banner `showConsentBanner()` Shows the Account Engagement consent banner, allowing the visitor to choose to give consent to Account Engagement analytics tracking. Example ```javascript pdt("showConsentBanner"); ``` ### Hide Consent Banner `hideConsentBanner( status)` Hide the Account Engagement consent banner from the page. If `true` or `false` is given, the `pi_opt_in` status is updated. If `null` is given, the banner is hidden and the status isn't updated. Example ```javascript // hide the consent banner pdt("hideConsentBanner", null); // hide the banner and set opt in status to false pdt("hideConsentBanner", false); // hide the banner and set opt in status to true pdt("hideConsentBanner", true); ``` ### Set Opt In `setOptIn( status)` Set the value of the `pi_opt_in` cookie. Account Engagement analytics only records page views when the value of this cookie is `true`. Example ```javascript pdt("setOptIn", true); ``` ### Revoke Consent `revokeConsent()` **Return**: undefined Deletes any existing visitor tracking cookies and sets the `pi_opt_in` cookie value to `false`. If the `pi_opt_in` cookie is true or unset a page view request is sent to Account Engagement. If your Account Engagement settings require the visitor to give consent based on their geo, then no page view is recorded and the Account Engagement consent banner is displayed. Example ```javascript pdt("revokeConsent"); ``` ### Clear Tracking Cookies `clearTrackingCookies()` Deletes all Account Engagement tracking cookies. Example ```javascript pdt("clearTrackingCookies"); ``` ## Interacting with Account Engagement Analytics Adding analytics actions to the queue is the primary way to interact with Account Engagement analytics. To retrieve data from the Account Engagement analytics tracker, pass a callback function into the queue. The callback function is executed when the queue is processed and it is passed a reference to the Account Engagement tracker. Since analytics is processed asynchronously, interacting with tracked values must be done within a callback function that is processed after the analytics library has loaded. In this example the current consent status is fetched, which then can be used to gate logic on your web page. ```javascript pdt(function (tracker) { let consentStatus = tracker.getConsentStatus(); if (consentStatus === false) { // take custom site action } }); ``` ### Get Property Value `get( propertyName)` **Return**: mixed Returns the value of a tracked property. Example ```javascript pdt(function (tracker) { let url = tracker.get("url"); }); ``` ### Get Consent Status `getConsentStatus()` **Return**: `null|boolean` Returns the current consent status for the Account Engagement tracker. If no consent status has been set, `null` is returned. Example ```javascript pdt(function (tracker) { let status = tracker.getConsentStatus(); }); ``` ## Writeable Analytics Parameters The following parameters can be updated using the `set` function. | Name | Type | Description | | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------- | | `url` | String | The url of the tracked page. default: document.URL. | | `title` | String | The title of the tracked page. default: document.title. | | `referrer` | String | The referring location to the tracked page. default: document.referrer or query string param 'referrer' if it exists. | | `piEmail` | String | Manually link a visitor to a prospect by email address. Must be a valid email address. | | `piPoints` | Integer | Manually override score for page view. | | `piProfileId` | Integer | Manually set the profile for visitors. | | `utmCampaign` | String | Google Analytics parameter. Can be used to set Account Engagement campaign. | | `utmMedium` | String | Google analytics parameter. Distinguishes Bing/Yahoo natural vs. paid search. | | `utmSource` | String | Google analytics parameter. Can be used to set the prospect's source field. | | `utmTerm` | String | Google analytics parameter. Used with an ad id in the Google Ad Keyword report. | # Tracking and Consent Use Cases and Examples Use the Tracking and Consent API to accomplish these use cases. ## Account Engagement Analytics in Single Page Applications A Single Page Application (SPA) loads all of its navigation resources with the initial page load. As users navigate the site, the page is updated dynamically rather than with traditional page loads. In order to capture page views in an SPA, you must send manual page views to Account Engagement to be recorded. There are many ways to handle and route requests in SPAs. In this example, there’s a listener that waits for a visitor to click navigation elements that have the `navigation-link` class. The listener sets the tracked page title to the text of the navigation link, and then sends an analytics request to Account Engagement to record the page view. ```javascript Home About ``` ## Syncing Account Engagement Opt in with Third-Party Consent Management If you’re using a third-party consent manager you can sync Account Engagement’s opt in status to match by using the `setOptIn` analytics action. ```javascript ``` ## Redisplay the Account Engagement Consent Banner Cookie consent laws and regulations vary by region. The Tracking & Consent Javascript API can help ensure that you’re always compliant, while also respecting the privacy of visitors interacting with your content. The consent banner is loaded with HTML from your account’s tracking opt-in preferences. You can display the banner when necessary. ```javascript ``` A call to `showConsentBanner` from the Tracking & Consent JavaScript API resurfaces the consent banner, letting website visitors change their consent preferences. You can use buttons or links on your website to let users reopen the banner. ```javascript ``` Calling `hideConsentBanner` hides the Consent banner element. ```javascript ``` # Transitioned from Version 3 to Version 4? Version 4 was created to accommodate multiple prospects with the same email address. If your Account Engagement business unit has the allow multiple prospects with the same email address (AMPSEA) feature enabled, then use version 4. If your Account Engagement business unit doesn’t have AMPSEA enabled, use version 3. To determine if your Account Engagement business unit has AMPSEA enabled, [check out this guide.](https://help.salesforce.com/articleView?id=sf.pardot_admin_ampsea_parent.htm&) If you want to enable AMPSEA in your Account Engagement business unit, use the following guidelines to keep using Account Engagement APIs. ## Request Path Changes Update your requests to use the `/version/4` path. For example: Before: ```bash GET: https://pi.pardot.com/api/prospect/version/3/read/id/1 ``` After: ```bash GET: https://pi.pardot.com/api/prospect/version/4/read/id/1 ``` ## Prospect API Changes Most of the differences between version 3 and version 4 are in the prospect APIs. - **New reference field:** Prospects can be referenced using the Salesforce CRM Identifier, the `fid` field. This `fid` field refers to the ID of the Lead or Contact record in Salesforce. You can find the lead ID (begins with 00Q) or the contact ID (begins with 003) in the URL when viewing a lead or contact record. Or, you can get multiple contacts or lead ID from Salesforce using the export tool. lead_identifier_example - **Create:** Prospects can still be created with a referenced `email` address. If you call the create API with the same email address multiple times, each call creates a prospect. Previously, you would get an error. - **Read:** When making a read query, querying by `email` returns all prospects that share that email address. Querying by Account Engagement `id` or Salesforce `fid` only returns the one matching prospect. - **Update:** Because there can be multiple prospects with the same email address, prospects can no longer be updated when referenced via `email` alone. Instead, use either the Account Engagement `id` or Salesforce `fid` references. - **Upsert:** Upsert query by `email` _always_ creates a prospect. Upsert by Account Engagement `id` or Salesforce `fid` updates or creates as needed. See [Upserting Prospects](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md#prospect-upsert) for more details. - **Delete:** Delete query must reference by Account Engagement `id` or Salesforce `fid`. - **Batch processing:** See examples of batch processing in the Prospect object documentation. See the [Prospect object documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/prospects-v4.md). ## Opportunity API Changes - **Create:** Creating an opportunity using a `prospect_email` reference must correspond to an existing prospect. If there are multiple prospects with that email address, the prospect with the most recent activity date is used. If you want to apply the opportunity to a specific prospect, then reference the prospect using `prospect_id`. - **Query:** If you query using a `prospect_email` reference, you receive opportunities that correspond with any prospects that share that email address. if you want a specific prospect then query by the `prospect_id`. See the [Opportunity Object documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/opportunities-v4.md). ## Visitor API Changes - **Assign:** Assigning by `prospect_email` alone (no `prospect_id`) returns an error. See the [Visitor Object documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v4/visitors-v4.md). # Transitioning to V5? Version 5 works with both Allow Multiple Prospects with Same Email Address (AMPSEA) and non-AMPSEA business units. Determine if your Account Engagement business unit has AMPSEA enabled. [Learn more in Help](https://help.salesforce.com/articleView?id=sf.pardot_admin_ampsea_parent.htm&) ## Request Path Changes Update your requests to use the Version 5 path. For example: Before: Version 3: ```bash GET: https://pi.pardot.com/api/prospect/version/3/read/id/1 ``` Version 4: ```bash GET: https://pi.pardot.com/api/prospect/version/4/read/id/1 ``` After: ```bash GET https://pi.pardot.com/api/v5/objects/prospects/1?fields=id,firstName,lastName,email ``` ## Prospect API Changes - **Create:** Prospects can be created with a referenced `email` address. If AMPSEA is enabled and you call the create API with the same email address multiple times, each call creates a prospect. - **Read/Query:** When making a read query, querying by `email` returns all prospects that share that email address. Querying by Account Engagement `id` only returns the one matching prospect. - **Update:** In version 5, an update must specify a prospect by id. In version 3 it was possible to specify a prospect by email address. - **upsertLatestByEmail:** UpsertLatestByEmail will find the most recently updated prospect by the `email` supplied and upsert that record. If a record with that email does not exist, one will be created. See [Upserting Prospects](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/prospect-v5.md) for more details. - **Delete:** Delete query must be referenced by Account Engagement `id`. See the [Prospect Object documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/prospect-v5.md) ## Visitor API Changes - **Assign:** Assigning must be done by `prospectId`. See the [Visitor Object documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/visitor-v5.md). ## Salesforce Connector API V5 introduces the Salesforce Connector API which allows for managing the status of your business unit's Salesforce Connector status. ## Bulk Actions V5 introduces bulk actions which allows for mass deleting records asynchronously. For example, up to 100,000 prospects can be deleted in one request. See the [Bulk Actions documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/bulk-actions-v5.md). ## Forms API Changes The V5 API has updated the forms API has been expanded to include several new features including creating forms, reordering form fields, adding/removing tags, and copying to CMS. The V5 API has also added endpoints for [Form Fields](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/form-field-v5.md), [Form Handlers](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/form-handler-v5.md), and [Form Handler Fields](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/form-handler-field-v5.md). See the linked documentation for more details. ## Visitor Page View API V5 adds the Visitor Page View API which allows for Read and Query of Visitor Page Views. See [Visitor Page View documentation](https://developer.salesforce.com/docs/marketing/pardot/guide/v5/visitor-page-view-v5.md). # Use Cases for Account Engagement API Extend Account Engagement to fit your business needs, providing access to your data for use in various ways. The API has so many possibilities that it can feel overwhelming to get started, so we’ve rounded up a few common use cases here. Start with these examples, then get creative. ## Data Augmentation You can use the Account Engagement API to clean and enrich prospect data, saving your sales reps hours of time spent on menial tasks. Automate data clean up tasks like normalizing picklist values, capitalizing names, and formatting phone numbers. You can also add data from your vendors by updating prospects via the API. **Example** Your manager asks you to fix all prospect name fields that are in all-caps or lowercase. They also want you to update prospect scores regularly, based on an internal scoring tool. You write some code that checks each prospect name and updates the capitalization. You set it up to run when a new prospect is added, keeping the database neat. You then set up an integration between your internal scoring tool and Account Engagement that updates the prospect score field every day. **Account Engagement Objects** - Prospect: get prospect data, update prospect field values ## Advanced Reporting Use the Account Engagement API to automate exporting visitor data to your own external analytics tools for richer insights. **Example** The marketing team wants a detailed analysis of all the web analytics to see how much budget they need to drive clicks and sync web ad targeting. You automate a bulk export of Account Engagement visitor data, then import it into your company’s analytics tool at regular intervals. **Account Engagement Objects** - Visitor Activity (via the Export API) - Prospect: get prospect data - Prospect Account: get prospect account data ## Enhanced Segmentation Use the Account Engagement API to help you target the right groups of prospects, so you can optimize your messaging and personalization. If another system contains most of your data, you can segment prospects in that system instead of Account Engagement. In this case, use the API to get the prospect data you need. Do your segmentation analysis outside of Account Engagement so you can update the prospects. Then, import the updated prospects into Account Engagement and add them to lists for engagement programs and other marketing efforts **Example** A marketing manager at your company wants to create an Account Engagement list for a new marketing initiative, but the information for the segmentation criteria is hosted outside of Account Engagement. The manager gives you a list from an external database, and the list includes Account Engagement prospect IDs. You use the Create operation with the List object and create an Account Engagement list. **Account Engagement Objects** - Prospect: get prospect IDs - List: Read or Create the List for the segment - List Membership: Add or remove prospects from the list # Version 3 and 4 Overview The Account Engagement API lets your application access current data within Account Engagement. Through the API, you can perform several common operations on Account Engagement objects including the following: - `create` -- Creates an object with the specified parameters. - `read` -- Retrieves information about the specified object. - `query` -- Retrieves objects that match specified criteria. - `update` -- Updates elements of an existing object. - `upsert` -- Updates elements of an existing object if it exists. If the object does not exist, one is created using the supplied parameters. You must authenticate using a Salesforce OAuth endpoint. See [Authentication](https://developer.salesforce.com/docs/marketing/pardot/guide/authentication.md) for more. Keep a few considerations in mind when you perform requests. For `update` requests, only the fields specified in the request are updated. All others are left unchanged. If a required field is cleared during an `update`, the request is declined. ## Request Format All requests to the API: - Must use either HTTP `GET` or `POST` - Must pass the access token. - Must pass Account Engagement Business Unit ID in an HTTP `Pardot-Business-Unit-Id` header (obtained using Salesforce OAuth) to authenticate. - Must use the correct URL for your Account Engagement environment. See [Test and Production Environments](https://developer.salesforce.com/docs/marketing/pardot/guide/overview.md#test-and-production-environments). ## Sample GET Request These examples use a production environment, so the domain is `pi.pardot.com`. If you are using a test environment, your domain is `pi.demo.pardot.com`. See [Test and Production Environments](https://developer.salesforce.com/docs/marketing/pardot/guide/overview.md#test-and-production-environments). ```bash GET https://pi.pardot.com/api//version/3/do///? HTTP/1.1 Authorization: Bearer Pardot-Business-Unit-Id: ``` ## Sample POST Request ```powershell POST https://pi.pardot.com/api//version/3/do/// HTTP/1.1 Authorization: Bearer Pardot-Business-Unit-Id: ``` ### Request Parameters | **Parameter** | **Required** | **Description** | | ------------------------- | ------------ | ------------------------------------------------------------------------------------------- | | `object` | X | The object type to be returned by the API request | | `op` | X | The operation to be performed on the specified object type | | `id_field` | X | The field to be used as the identifier for the specified object | | `id` | X | The identifier for the specified objects | | `access_token` | X | The access token obtained during [Authentication](https://developer.salesforce.com/docs/marketing/pardot/guide/authentication.md) | | `pardot_business_unit_id` | X | The Account Engagement business unit. For details see [Authentication](https://developer.salesforce.com/docs/marketing/pardot/guide/authentication.md) | | `format` | | The API data format: either xml (default) or json | | `params` | | Parameters specific to your request; See individual methods for details | The ordering of parameters is arbitrary. Parameters are passed using conventional HTML parameter syntax, with `'?'` indicating the start of the parameter string (for GET requests only) and `'&'` as the separator between parameters. With the exception of `` and ``, all components are required. Data returned from the API is formatted using JSON or XML 1.0 with UTF-8 character encoding. Keep in mind that some characters in the response can be encoded as HTML entities, requiring client-side decoding. Also, keep in mind that all parameters specified in an API request MUST be URL-encoded before they are submitted. In general, the API returns XML or JSON containing a current version of the target object's data. But unsuccessful requests return a short response containing an error code and message. See Error Codes & Messages for error descriptions and suggested remedies: [Error Codes and Messages](https://developer.salesforce.com/docs/marketing/pardot/guide/error-codes.md) ## Changing the API Response Format The Account Engagement API supports several output formats, and each returns different levels of detail in the XML or JSON response. Output formats are defined by specifying the `output` request parameter. Supported output formats include: - `full` -- Returns all supported data for the Account Engagement object and all objects associated with it. - `simple` -- Returns all supported data for the Account Engagement object. - `mobile` -- Returns an abbreviated version of the object data. This output format is ideal for mobile applications. - `bulk` -- Returns basic data for an object (does not provide total object count). Used for querying [large amounts of data](https://developer.salesforce.com/docs/marketing/pardot/guide/bulk-data-pull.md). If the output request parameter is not defined, the output format defaults to `full`. See the XML Response Format sections for each object for details about the formats. ## Sample Code Here's an example of calling the Account Engagement API using a simple PHP client using the cURL library. Note: We strongly recommend **against** using PHP's `file_get_contents` function to call the Account Engagement API because it makes error handling cumbersome. ```php apiVersion = $apiVersion; $this->format = $format; } /** * @param string $endpoint * @param string $operation * @param array $data * @param array $headers * @param array $queryParams * @return array * @throws Exception */ public function post(string $endpoint, string $operation, $data = [], $headers = [], $queryParams = []) { $curl_handle = $this->initRequest($endpoint, $operation, $headers, $queryParams); curl_setopt($curl_handle, CURLOPT_POST, true); // Add POST data if given if (!empty($data)) { curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $data); } return $this->executeCall($curl_handle); } /** * @param string $endpoint * @param string $operation * @param array $headers * @param array $queryParams * @return array * @throws Exception */ public function get(string $endpoint, string $operation, $headers = [], $queryParams = []) { $curl_handle = $this->initRequest($endpoint, $operation, $headers, $queryParams); return $this->executeCall($curl_handle); } /** * @param string $endpoint * @param string $operation * @param array $headers * @param array $queryParams * @return false|resource */ private function initRequest(string $endpoint, string $operation, $headers = [], $queryParams = []) { // Construct our full URL to the Account Engagement API $url = $this->buildUrl($endpoint, $operation); // Add desired format to any query string params provided $queryParams['format'] = $this->format; // Build query string params into an encoded string $queryString = http_build_query($queryParams, null); // Append query string params to URL $url .= "?{$queryString}"; // Init curl handle and set standard curl options: timeouts / require SSL / verify SSL $curl_handle = curl_init($url); curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($curl_handle, CURLOPT_TIMEOUT, 30); curl_setopt($curl_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1); // Add any headers passed in such as Authorization header if (!empty($headers)) { curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $headers); } return $curl_handle; } /** * @param string $endpoint * @param string $operation * @return string */ private function buildUrl(string $endpoint, $operation = "") { if ($endpoint === 'login') { return self::SALESFORCE_OAUTH_TOKEN_URL; } return self::BASE_URL . "{$endpoint}/version/{$this->apiVersion}/do/{$operation}"; } /** * @param $curl_handle * @return array * @throws Exception */ private function executeCall($curl_handle) { // Execute our call to the Account Engagement API $rsp = curl_exec($curl_handle); // Gather the HTTP response code and last effective URL called $httpCode = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE); $url = curl_getinfo($curl_handle, CURLINFO_EFFECTIVE_URL); // Handle errors in calls, this could be a log or an exception thrown as written here if (!$rsp) { $errorMessage = curl_error($curl_handle); curl_close($curl_handle); throw new Exception("Error calling API. HTTP Code: {$httpCode}. Message: {$errorMessage}"); } curl_close($curl_handle); // Output call response for informational purposes echo("URL: {$url}" . PHP_EOL); echo("HTTP Response Code: {$httpCode}" . PHP_EOL); echo("Response: {$rsp}" . PHP_EOL . PHP_EOL); return [$httpCode, $rsp]; } /** * Use Account Engagement API with a SSO user. * Getting the access token and using that to use the Account Engagement API. */ public function executeRequests() { // Setup user credentials $credentials = [ "grant_type" => "password", "client_id" => "", "client_secret" => "", "username" => "", "password" => "" ]; $pardot_business_unit_id = ""; // Authenticate to Salesforce - Must be a POST with credentials in the message body list($httpCode, $rsp) = $this->post('login', '', $credentials, null, [], true); // Capture the access_token from a successful login response $access_token = json_decode($rsp, true)['access_token']; // Create Authorization Header from access_token and business unit $authHeader = ["Authorization: Bearer {$access_token}", "Pardot-Business-Unit-Id: {$pardot_business_unit_id}"]; // Call Prospect Query list($httpCode, $rsp) = $this->get('prospect', 'query', $authHeader, ['limit' => 1]); // Call VisitorActivity Query list($httpCode, $rsp) = $this->get('visitorActivity', 'query', $authHeader, ['limit' => 1]); // Create a Campaign list($httpCode, $rsp) = $this->post( 'campaign', 'create', ['name' => 'A Campaign', 'cost' => 100], $authHeader ); } } // Prepare to call version 3 or 4 of the API with JSON or XML responses $client = new SamplePardotApiClient(4, 'json'); // Authenticate to Account Engagement - Using Salesforce OAuth $client->executeRequests(); ``` # Work with Extensibility Features Extensibility features include external activities and external actions. These tools help streamline workflows and automate tasks by connecting third-party apps to Account Engagement. External activities feed prospect activity data into Account Engagement where it can be used in automations. External actions can be used in Engagement Studio programs to execute actions in a third-party app. Before you start, familiarize yourself with these features by reviewing [Automate Data Sharing with Third-Party Apps](https://help.salesforce.com/s/articleView?id=pardot_extensibility_parent.htm). ## Get Started with Extensibility Create a marketing app extension in Account Engagement Setup for each third-party app you work with. For each extension, add external activities and actions as needed. Activity-type and action-type objects represent external activities and actions, respectively. Each extension is associated with a business unit. The steps to configure an external activity and an external action are different, but some preliminary steps are the same for both types. ### Set Up Authentication To set up marketing app extensions and related activity type and action type records via the API, set up Salesforce OAuth and authenticate to Tooling API. For general information about setting up OAuth, see [Authentication](https://developer.salesforce.com/docs/marketing/pardot/authentication.md). For more information about the authentication methods for each feature, see [External Activity](https://developer.salesforce.com/docs/marketing/pardot/guide/external-activity-guide.md) and [External Actions](https://developer.salesforce.com/docs/marketing/pardot/guide/external-actions-guide.md). ### Consider a Managed Package Marketing app extensions, which include action types for external actions and activity types for external activities, can be packaged. A managed package lets admins install an extension from AppExchange with the click of a button. If you’re a third-party service and building a generic integration, consider creating a managed package with the connected app. Make sure the marketing app extensions you create have unique and identifiable names. Use [Tooling API](https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/intro_api_tooling.htm) to set up the extension and activity types metadata. In this guide, we use the REST Tooling APIs. We recommend that when your customer’s Salesforce Admin runs the setup that they run it without persistent authentication and name a different user for execution. Don’t create a business-unit assignment for packaged extensions. The end user of your integration must create the business-unit assignment. We also recommend that you leave all packaged components for automations deactivated. ## General Considerations Keep these considerations in mind when working with marketing app extensions and related objects. - Before you work with extensibility features, review the considerations in [Automate Data Sharing with Third-Party Apps](https://help.salesforce.com/s/articleView?id=sf.pardot_extensibility_parent.htm). - To use Tooling API, you must be a Salesforce admin. You can also set up a Marketing admin user that has access to Tooling API. See [Designate an Admin for Marketing Setup Tasks](https://help.salesforce.com/articleView?id=sf.pardot_admin_marketing_admin.htm). - You can create marketing app extensions, activity types, and action types using Tooling API or in Marketing Setup in Salesforce. - External activities aren’t available for packaging, but they can be configured using Tooling API. - To use external activities and external actions in automations, the marketing app extension and activity or action type must be marked active for automations. The marketing app extension must also be assigned to the correct business unit. ## See Also - _Trailhead_: [Extensibility Features for Account Engagement](https://trailhead.salesforce.com/content/learn/modules/pardot-external-activities-quick-look)