Overview

Useful code samples, data examples, or commands will appear in this column throughout the documentation. You can use the navigation above to select which language examples work best for your team!

$> curl https://example.com/path/to/resource?query-param=value
import antigravity

Welcome to Pendo’s API documentation. If you’re looking for how to install Pendo into your application, how Pendo collects visitor analytics from your application, and how you can retrieve or extract those analytics data from Pendo for external consumption, you’re in the right place. Pendo provides the following APIs and integration kits for customers:

This overview will introduce you to some key concepts when using Pendo and installing the Pendo Agent.

Introduction

Once installed in your application, visitor activity is collected automatically by the Pendo Agent and sent via Image Beacons to Pendo for data processing. Pendo accepts these events immediately but ingests and processes visitor data asynchronously. So visitor events sent by the Agent are not immediately available via the API but usually within 5 minutes of receipt. The Guide system in the Agent that provides in-app messaging fast-tracks visitor events in order to consider new visitors and visitor attributes immediately when calculating eligibility of Guides, however.

Pendo’s Aggregation API allows you to request structured transformations of the events collected by the Agent across all visitors. It supports arbritrary grouping, filtering and projections, as well as selecting and merging object-specific analytics for Pages, Features, Guides and Track Types. Practically all of the charts, graphs and reports provided in the Pendo interface are generated by the sources and operations provided.

The Pendo Agent automatically tracks most browser events by default as Auto Events, regardless of their association with existing Features. If you need to track specific actions that aren’t represented by simple browser events, you can send Track Events to represent any type of behavior that you like. The Track API allows you to interact with these events when they’re processed. New Track Types are created automatically when an event is processed.

Installation

Anatomy of the Pendo Snippet:

This snippet is used primarily to explain how it works. If you are installing it, make sure to copy it from the "Subscription Settings" for your App.

// Add to the end of your `<body>` tag just before the `</body>`...
<script>
// Immediately-invoked function expression to prevent scope pollution...
(function(apiKey){ // <-- passed in at the bottom
    /**
     * Bootstrap the `pendo` namespace for deferred execution of common methods
     * until the Agent is fully loaded from the CDN. The deferred methods are:
     * - initialize
     * - identify
     * - updateOptions
     * - pageLoad
     */
    (function(p,e,n,d,o){var v,w,x,y,z;o=p[d]=p[d]||{};o._q=[];
    v=['initialize','identify','updateOptions','pageLoad'];for(w=0,x=v.length;w<x;++w)(function(m){
        o[m]=o[m]||function(){o._q[m===v[0]?'unshift':'push']([m].concat([].slice.call(arguments,0)));};})(v[w]);
        // Create a `<script>` tag linked to your application-specific Agent build from our CDN...
        y=e.createElement(n);y.async=!0;y.src='https://cdn.pendo.io/agent/static/'+apiKey+'/pendo.js';
        z=e.getElementsByTagName(n)[0];z.parentNode.insertBefore(y,z);
    })(window,document,'script','pendo');

    // Call this whenever information about your visitors becomes available
    // Please use Strings, Numbers, or Bools for value types.
    pendo.initialize({
        visitor: {
            id:              'VISITOR-UNIQUE-ID'   // Required if user is logged in
            // email:        // Optional
            // role:         // Optional

            // You can add any additional visitor level key-values here,
            // as long as it's not one of the above reserved names.
        },

        account: {
            id:           'ACCOUNT-UNIQUE-ID' // Highly recommended
            // name:         // Optional
            // planLevel:    // Optional
            // planPrice:    // Optional
            // creationDate: // Optional

            // You can add any additional account level key-values here,
            // as long as it's not one of the above reserved names.
        }
    });
})('YOUR_PENDO_API_KEY'); // <--- You should change this.
</script>

Installation of the Pendo Agent is very easy: just include the Pendo snippet in your application as supplied on your initial "Setup" page or "Subscription Settings" for one of your Apps. If your application is a Server-Side-Rendered (SSR) application, you include the snippet on every generated HTML view, usually by placing it in a shared layout template. If your application is a Single-Page-Application (SPA), you include the snippet outside of your main application container as if it were an external library.

You SHOULD NOT include the snippet multiple times in the same HTML page, whether by inclusion in a partial that is included in other templates multiple times or in an HTML element that is reloaded or re-rendered within the browser. Calling pendo.initialize reinitializes the Agent completely, leading to noisy analytics.

If you prefer, you can use Segment to install Pendo or use Google Tag Manager to install Pendo within your application. For more information and a step-by-step guide to installing and configuring visitor and account metadata for your application via the Pendo snippet, review the Snippet Installation Guide in the Pendo Help Center.

Agent API

The Agent API allows developers to interact with the Pendo Agent that collects user interaction and displays in-app messaging. There’s mostly no need to use this API as the default installation provides everything needed to effectively capture Auto Events and deliver Guides to your end-users. Advanced functionality like sending Track Events, Debugging, and programatically activating Guides requires interaction with the Agent API inside your application JavaScript.

NOTE: any undocumented functionality you encounter while inspecting the pendo namespace should be considered either internal or experimental and is subject to change. Although it may go without saying, don’t rely on undocumented functionality!

Browser Interactions

Pendo automatically tracks a specific list of native browser events, just by installing it. We call this Automatic Event Collection and the Auto Events that the Agent collects are:

  • load on the <body> element, including the contents of the <title> tag and the URL.
  • click on any element, even elements that don’t normally listen for clicks.
  • focus and change on any <form> field element, i.e. <input>, <select>, <textarea>, <button>
  • submit on the <form> element submitted

In all cases, Pendo collects the exact path to the target element of the event and the URL on which the element appeared. The element path includes relevant information about each DOM node along the way, dependent on the target tag. For example, a click event on an <a href="..."> tag collects the value of the href attribute. What attribute values are collected by default can be configured with Agent Options, but here’s a quick snapshot of what we collect by default:

Tag Attributes
<a> href
<img> src, alt

Pendo will avoid collecting the value attribute of any <input> elements clicked, except where that value is typically useful for targeting Features, namely <button> and button-like elements.

Tag Attributes
<button> name, value
<input> name, type
<input type="submit"> name, type, value
<input type="button"> name, type, value

Additionally, the Agent sends a virtual identify event when the current visitor is uniquely identified by your application, either by providing the visitor configuration object to pendo.initialize() or by invoking pendo.identify(). Updates to the identifying information, Visitor Metadata, for your visitors are sent via meta virtual events. See Functions below for more.

Functions

Initialization and Identification

Examples:

pendo.initialize({
    visitor: {
        id: "PUT_VISITOR_ID_HERE",
        name: "Neo",
        email: "[email protected]",
        role: "godlike"
    },
    account: {
        id: "PUT_ACCOUNT_ID_HERE",
        name: "CorpSchmorp"
    }
});

String arguments:

pendo.identify(
  "PUT_VISITOR_ID_HERE",
  "PUT_ACCOUNT_ID_HERE"
);

Object arguments:

pendo.identify({
    visitor: {
        id: "PUT_VISITOR_ID_HERE",
        name: "Neo",
        email: "[email protected]",
        role: "godlike"
    },
    account: {
        id: "PUT_ACCOUNT_ID_HERE",
        name: "CorpSchmorp"
    }
});
function
initialize() Completely re-initialize the Agent with new options, which does NOT reload Guides automatically. See loadGuides instead.
identify(visitorId, accountId?) identify({ visitor, account? }) Send an identify event and a meta event. This function accepts either a string for just the visitor id or it accepts an Object that will contain at least a visitor object with at least an id field.
isReady() Returns true when the Agent is fully loaded and has an API key.
flushNow() Force a flush of cached event objects. This function returns a then-able Promise compatible with the Promises/A+ spec that is resolved when all events have been sent and rejected in case an error occurs.
updateOptions() After initialize has been called, updates one or more visitor metadata fields.
getVersion() Returns the string for the current Version of the Agent.
getVisitorId() Returns the id for the visitor currently being applied to any events being sent to Pendo. Will always be set either by host application or as a generated id.
getAccountId() Returns the id for the account currently being applied to any events being sent to Pendo.
getCurrentUrl() Gets the current URL that is sent on all events.

Guides and Guide Center

function
findGuideByName(name) Returns a Guide object for the given name, if loaded.
findGuideById(id) Returns a Guide object for the given id, if loaded.
showGuideByName(name) Activates the Guide for the given name, if loaded.
showGuideById(id) Activates the Guide for the given id, if loaded.
toggleLauncher() Causes the Guide Center to toggle visibility, if the Guide Center is eligible for the current URL.
removeLauncher() Removes the Guide Center completely until a full page reload.

Troubleshooting

function
loadGuides() Manually reload the eligible Guides for the current visitor and URL.
startGuides() Restart the Guide display subsystem and show the first eligible Guide loaded.
stopGuides() Clear any showing Guides and prevent any loaded Guides from rendering but does not drop the loaded Guides from memory. Call startGuides() after a stopGuides() call.

Debugging

In Agent versions 2.10+, you can debug and troubleshoot Guides with our debugging tool. Enable the debugging extension by invoking pendo.enableDebugging() in the JavaScript console on a page that has the Pendo Agent installed. A small pink bug icon should appear in the top left corner of your window only. Click on that icon to reveal a panel of information about the currently loaded and active sub-systems running.

Function
enableDebugging() Extends the global pendo object to include additional APIs for debugging purposes.
disableDebugging() Removes the debugging extensions.
isDebuggingEnabled(coerce?) Returns a string indicating debugging status — 'Yes' or 'No' — or pass true as coerce to get a Boolean value instead.

To stop debugging and remove the icon, invoke pendo.disableDebugging() in the JavaScript console.

NOTE: when enabled, the debugging icon is only visible to you. None of your users will ever see it.

Example function

pendo.debugging.getEventCache();
function
getEventCache() Returns the initial buffer of unsent events.
getAllGuides() Returns all Guides for the current visitor.
getAutoGuides() Returns all Guides that have "Automatic" activation method.
getBadgeGuides() Returns all Guides that are activated via a Badge.
getLauncherGuides() Returns all Guides that are activated via the Guide Center.

Events

Examples

pendo.events
  .ready(function() {
    // Do something once `pendo.isReady()` would return `true`
  })
  .guidesLoaded(function() {
    // Do something when Guides load
  })
  .guidesFailed(function() {
      // Do something when Guides fail to load
  });

Example snippet passing event handlers in pendo_options

pendo.initialize{
    apiKey: 'YOUR_API_KEY',
    visitor: { /* visitor `id` and metadata */ },
    account: { /* account `id` and metadata */ },
    events: {
        ready: function () {
            // Do something when pendo is initialized
        }
    }
}

The Agent implements a simple event emitter pattern for specific synthetic events that customer applications might be interested in. Your application can register handlers for these events via the pendo.events methods or by specifying handlers in pendo.initialize(options)

handlers
ready Triggered when the Agent is loaded and initialized, i.e. isReady would return true.
guidesLoaded Triggered when Guides have loaded successfully, including any associated content assets.
guidesFailed Triggered when Guides fail to load because of a network error or timeout, when guideTimeout or guides.timeout is set to a numeric value in milliseconds.

Track Events

Some examples of collecting Track Events with pendo.track:

// Side-effect of user interaction: recording membership level
User.registerViaFacebook(payload)
  .then(doStuffAfterRegistering)
  .catch(handleRejection)
.finally(user => {
  pendo.track("User Registered", {
    userId: user.id,
    plan: user.plan,
    accountType: "Facebook"
  });
});

// Monitoring an interesting error case
try {
  this.thing.thatBreaks(sometimes);
} catch (error) {
  pendo.track("JIRA-12345--error-tripped", {
    message: error.message,
    stack: error.stack
  });

  handleThrown(error);
}

For situations in which Auto Events are insufficient alone to track visitor activity or when your application needs to send additional events to describe that activity, Agent 2.14.3+ includes pendo.track(name, metadata?) that your application can invoke to send synthetic events. These are collected in the same manner as regular events, automatically recording the time and URL at which the event was triggered. Each Track Event requires a trackType that uniquely identifies it during event processing, analogous to the click or focus types of Auto Events. Additional metadata about the event must be supplied in the function call. You can view the different trackType values and associated analytics that have been processed on the Track Events list.

Function
track(trackType, metadata?) Queue a trackType event or transmission, optionally including metadata as the payload for the event.

Since the Pendo Agent automatically collects Auto Events, you only need to use Track Events judiciously to track side-effects of user interactions, like creating or deleting a record, or for logging a specific error case for monitoring purposes. Track Events can transmit any arbitrary data in their metadata payload, even different payloads for the same Track Type. This metadata will be available in the timeline charts in Pendo for inspection and can be queried using the Aggregation API.

For more on Track Events inside of Pendo and how to send them via Segment.io, see "Track Events" on the Pendo Help Center.

Guide Events

The Guide sub-system tracks user interactions with displayed Guides through a series of Guide Events transmitted to Pendo whenever a Guide is presented or otherwise interacted with.

Events
guideSeen Emitted every time a Guide Step is presented
guideAdvanced Emitted every time a Guide Step is advanced via onGuideAdvanced
guideDismissed Emitted every time a Guide Step is dismissed via onGuideDismissed

Additionally, the following functions can be used inside of the JavaScript for Guides to control the currently displayed Guide or Guide Step by emitting the corresponding Guide Events.

onGuideAdvanced

Inside the HTML for a Guide, provide a clickable element, like an <a> or <button> tag:

    <button class='_pendo-guide-next_'>Show me more!</button>

Using the HTML above, you can advance to the next step of the current Guide:

// Immediately-Invoked Function Expression, named to make debugging easier...
(function wireGuideAdvanceButton(step) {
    // `GuideStep.attachEvent` is a cross-browser compatible version of `addEventListener`...
    step && step.attachEvent(step.guideElement[0], 'click', function (e) {
        // `pendo.dom` is a lightweight jQuery-like DOM selection API...
        var advanceButton = pendo.dom(e.target || e.srcElement)
            .closest('._pendo-guide-next_');

        if (advanceButton.length) {
            // Advance to the next Guide Step...
            pendo.onGuideAdvanced();
        }
    });
})(step, guide);
// The `step` and `guide` are made available inside the Guide JS...

Or if you want to advance multiple Guide Steps:

         if (advanceButton.length) {
-            // Advance to the next step of the current Guide...
-            pendo.onGuideAdvanced();
+            // Advance _two_ steps ahead in the current Guide...
+            pendo.onGuideAdvanced({ steps: 2 });
         }

For example, if you had a 4 step guide and the first step was visible, this would advance the first and second steps, and display the third step.

Invoking this function causes another Guide Step in the current Guide to be displayed and sends a guideAdvanced event to synchronize with the backend Guide system. As above, displaying a Guide Step will also send a guideSeen event for the newly displayed Guide Step.

Parameters
none Advance to the next Guide Step in a multi-step Guide and send a guideAdvanced event.
GuideStep step Advance to the provided Guide Step within the current Guide.
{ steps: count } Advance count number of Guide Steps within the current Guide. Each Guide Step skipped also emits a guideAdvanced event.

onGuidePrevious

If the previous Guide or Guide Step is eligible for the current URL, provide an <a> tag with no href attribute in the HTML for the Guide Step:

<a class='_pendo-guide-previous_'>Back</a>

Otherwise, the href should point to the correct URL for the previous Guide Step:

<a class='_pendo-guide-previous_' href='/url/for/previous/step'>Back</a>

In the JavaScript panel, you can use a similar approach as with onGuideAdvanced to wire up onGuidePrevious:

// Immediately-Invoked Function Expression, named to make debugging easier...
(function wireGuidePreviousStepButton(step) {
    // `GuideStep.attachEvent` is a cross-browser compatible version of `addEventListener`...
    step && step.attachEvent(step.guideElement[0], 'click', function (e) {
        // `pendo.dom` is a lightweight jQuery-like DOM selection API...
        var previousStep = pendo.dom(e.target || e.srcElement).closest('._pendo-guide-previous_');

        if (previousStep.length) {
            // Return to the previous Guide Step...
            pendo.onGuidePrevious();
        }
    });
})(step, guide);

Invoking this function casues the previous Guide Step to be displayed and sends a guideSeen event to synchronize with the backend Guide system. The guideSeen event is sent immediately so that refreshing the browser or navigating to a different URL will display the intended Guide Step.

Parameters
none Redisplay the previous Guide Step.
GuideStep step Return to a previous Guide Step within the current Guide.

onGuideDismissed

To dismiss the currently displayed Guide, not just the Guide Step, add this to your HTML:

<button class='_pendo-guide-dismiss_'>No thanks</button>

Similar to above examples for onGuideAdvanced and onGuidePrevious in the JavaScript for your Guide Step:

// Immediately-Invoked Function Expression, named to make debugging easier...
(function wireGuideDismissButton(step) {
    // `GuideStep.attachEvent` is a cross-browser compatible version of `addEventListener`...
    step && step.attachEvent(step.guideElement[0], 'click', function (e) {
        // `pendo.dom` is a lightweight jQuery-like DOM selection API...
        var dismissButton = pendo.dom(e.target || e.srcElement).closest('._pendo-guide-dismiss_');

        if (dismissButton.length) {
            // Dismiss the entire Guide...
            pendo.onGuideDismissed();
        }
    });
})(step,guide);

Invoking this function causes the current Guide to be dismissed from display and emits a guideDismissed event to the backend Guide system. Dismissed Guides will not be re-displayed by default unless they have a recurrence setting or can be reactivated with an element. They can always be redisplayed via onGuideAdvanced or onGuidePrevious.

Parameters
none Dismiss the Guide, marking the current Guide Step as dismissed.
GuideStep step Dismiss a specific Guide Step within the current Guide.
{ until: 'reload' } Dismiss a Guide until the next page reload

Options

The following configuration options can be provided to the Agent in the pendo.initialize call immediately after your install snippet. The initialize method and a few others are stubbed in the snippet so that the Agent will run queued invocations when it becomes ready.

Config Option
apiKey Your API key, which is embedded in your install snippet. If you’re self-hosting the Agent by version, you’ll need to supply this option to get the Agent to run.
excludeAllText Do not collect the innerText from any element. Default is false.
excludeTitle Do not collect the contents of the <title> tag during load events. Default is false
disableCookies Do not use cookies for storing any values, defaulting to in-memory storage only. Default is false.
disablePersistence Do not use cookies to remember any Visitor identifiers or metadata, last seen Guide Step, and various other pieces of state. While this will prevent the Agent writing cookies, it will also ignore any identifiers already stored in cookies and may produce an increase of anonymous Visitors in Pendo, depending on how soon your application identifies the Visitor. Default is false.
guides.delay Guides will be loaded on initialize but not displayed initially. Call pendo.startGuides() to start the Guide sub-system. Default is false.
disableGuides Completely disables the Guides sub-system. Default is false. Set to true to disable guides.
guides.timeout How many milliseconds to wait for Guides to load. Default is infinity (i.e. wait forever).
guides.tooltip.arrowSize The size in pixels of the arrows for Tooltip Guides. Default is 15; omit the unit.

v1 API

API Base URL

https://app.pendo.io/api/v1/

The v1 API allows developers to request and modify resources like Guides, Visitor Metadata, and Reports and to make Aggregation queries using a MongoDB-like query language. All of the charts, graphs, and reports displayed in the main Pendo application are generated using similar queries.

Don’t have access to our API but still want to try things out? Each of the read-only examples below contain a sample integration key that can be used to query mock data. If you already have access and are looking for some sample aggregations, click the button below to load up a collection of requests that can be used against the aggregation endpoint. If you have questions or want to learn more about gaining access to our API, we recommend reaching out to your customer success manager or [email protected] and we’ll get you in touch with the right person.

Run in Postman

Note: All request and response bodies, including errors, are encoded in JSON. Pendo can throttle API calls if you exceed 100 calls per second to a single endpoint.

Authentication

Example request

curl -X GET \
  https://app.pendo.io/api/v1/report \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]'
import requests
url = "https://app.pendo.io/api/v1/report"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

A sample integration key is included in all of the read-only examples so you can test any of them right away. When you’re ready to test requests against your own subscription, simply replace the sample key with your actual integration key.

Authentication of requests is handled by an integration key. When enabled for the subscription, admins can create and manage those keys here.

Integration keys should be kept secret! It is how you securely access and update information about your users and accounts in Pendo. Do not share them in client-side javascript, publicly accessible code repositories, etc.

To create an Integration Key:

  1. Login to the Pendo Application as an Admin user.
  2. Visit the Integrations section in the Pendo App, and then click on Integration Keys.
  3. Click on the Add Integration Key button at the top right-hand side of the screen.
  4. Give your new key an appropriate description.
  5. If a read-write key is needed, tick the box marked Allow Write Access.
  6. Click on Create to finish.

The Integration Key is the UUID that is in the Key column of the table.

Status Codes

HTTP status code summary

200 - OK Everything worked as expected.
400 - Bad Request The request was unacceptable, often due to missing a required parameter.
401 - Unauthorized No valid integration key provided.
402 - Request Failed The parameters were valid but the request failed.
404 - Not Found The requested resource doesn’t exist.
422 - Unprocessable Entity The request could not process the payload. The syntax may be correct, but may be semantically wrong
429 - Too Many Requests Too many requests hit the API too quickly. Slow down.
500, 502, 503, 504 - Server Errors It’s not you, it’s us. We’re sorry.

We use conventional HTTP response codes to indicate the success or failure of an API request.

In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a resource was not able to be found or updated, etc.). The various HTTP status codes we might return are listed below.

Account

Account endpoint

https://app.pendo.io/api/v1/account/{accountId}

The account endpoint allows you to retrieve a single account’s specific details by supplying an account ID as part of your request. The {accountId} referenced below can be found on the accounts list page or at the end of the url when viewing an account details page.

The account object

Example response

[{
    "id": "Zeta and Sons",
    "metadata": {
        "agent": {},
        "auto": {
            "firstvisit": 1506349414089,
            "id": "Zeta and Sons",
            "idhash": 1129480058,
            "lastupdated": 1506349414757,
            "lastvisit": 1506349414089
        }
    }
}]
Attributes
id
string
Unique identifier for the account.
metadata
string
Displays various metadata for the specified account. agent, auto, custom, salesforce, and segmentio.

Get an account by ID

Definition

GET https://app.pendo.io/api/v1/account/{accountId}
requests.get("https://app.pendo.io/api/v1/account/{accountId}")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/account/Zeta%20and%20Sons \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]'
import requests
headers = {
    'content-type': 'application/json',
    'x-pendo-integration-key': '[add_your_pendo_int_key_here]',
}
requests.get('https://app.pendo.io/api/v1/account/Zeta%20and%20Sons', headers = headers)

Example response

[{
    "id": "Zeta and Sons",
    "metadata": {
        "agent": {},
        "auto": {
            "firstvisit": 1506349414089,
            "id": "Zeta and Sons",
            "idhash": 1129480058,
            "lastupdated": 1506349414757,
            "lastvisit": 1506349414089
        }
    }
}]

Gets an account object using an account ID.

Details
Method GET
URI /api/v1/account/{accountId}
Parameters accountId - URL encoded account id or b64_XXXX, where XXXX is a URL-safe base64 encoded account Id
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Aggregation

Aggregation endpoint

https://app.pendo.io/api/v1/aggregation

Aggregations are a query language for accessing and processing Pendo data. They take sources of Pendo data and apply operators to do computations. They run in the context of a given Pendo subscription and are written in JSON.

It is worth noting, the aggregation endpoint is not intended to be a bulk export feature, so breaking up aggregations by different time ranges may be necessary if you hit sizing or timeout limits. The aggregation endpoint cannot be used to query path or funnel reports.

Helpful Links:

Run in Postman

Data querying is performed using a flexible aggregation pipeline modeled after MongoDB. Each step of the pipeline takes rows as its input and output zero or more rows. The basic unit is a row which contains named fields (possible nested) fields. At a high level, an aggregation consists of

  • A row source and time specification
  • A pipeline for row processing

All input data rows for the specified time period are fed into the aggregation pipeline. The rows which those pipeline yields are the result of the aggregation; a pipeline may result in no rows or in many rows depending on the pipeline and the input.

If the time specification expands into 24 separate time periods (one for each hour of a day, perhaps) then 24 independent pipelines are run, and the aggregation will have 24 sets of results. Each of those results in independent of the others.

Nested Fields

Example structure

{
    "name": {
        "first": "bugs",
        "last": "bunny"
    }
}

Wherever a field name is needed, a dotted list of field names can be used to specify nested objects.

Nested specifiers can be used to create new fields as well; any missing intermediate objects will be initialized.

In the example to the right, the field name.last has the value bunny.

Data Stores

Data Stores
Visitors General information on all visitors Pendo has ever seen.
Accounts General information on all accounts Pendo has ever seen.
Events Each interaction with your application by a visitor. This includes click, page load, metadata, and guide events. The definitions of pages, features, and guides.

Expressions

A number of pipeline operators support expressions. Expressions follow basic C expression syntax along with function calls. Supported operators are ==, !=, &&, ||, <, >, <=, >=, +, -, /, *, %, and !.

All numeric value are converted to float’s for computational purposes, and C order of operation is used.

Parenthesis () may be used for grouping expressions.

The comparison operators can be used to compare strings, the logical operators and comparison work on boolean values, and the equality operators can compare two lists.

For the || and && operators, null is treated equivalently to false.

The == and != operators treat null as a distinct value (so null == null but null != false) and any other operator which has null as a parameter returns null as its value (so 1 + null == null). Looking up a field that does not exist in a row results in null.

Values may be extracted from list by using normal JavaScript style indexes such as listField[index]; sublists can be created using JavaScript style slices such as listField[start:end]. Additionally negative indexes can be used to look up items from the end; listField[-2] will return the next to last item in the list. This follows Python style syntax.

Arrays of values are supported, such as ["a","b","c"] or [1,1+2,sum(a)]. All array elements must be of the same type. You may select an element from the array using normal Javascript style indexes (i.e. ["a","b","c"][2]) as defined in the preceding paragraph.

Expression primitives are numbers (with or without a decimal point), strings enclosed in double quotation marks, true, false, and field names (using dotted notation to specify nested fields). The currently supported functions are listed below.

Functions
ceil(val) returns the ceiling of numeric value val
null if val == null
error if val is non-numeric/non-null
childAccountId(accountId) returns the child account id for the specified accountId
null if the accountId is not found
contains(listValue, item) returns true if item is in the specified list
contains(haystackString, needleString) returns true if the needle is contained in the haystack (both as strings)
floor(val) returns the floor of numeric value val
null if val == null
error if val is non-numeric/non-null
formatTime(goFormatString, timeInMillis) formats the given time using the go-style go format string examples.
hash(string) returns a 32 bit hash value for the given string
if(testExpression, ifTrue, [ifFalse]) returns ifTrue if testExpression is true
returns ifFalse (or null when ifFalse missing) otherwise
ifNull(val, defaultVal) returns val if val is not null
returns defaultVal otherwise
Note: shorthand for (and preferred over) if(isNull(val), defaultVal, val)
isNull(field) returns true if field is null or does not exist
returns false otherwise
len(listField) returns the length of the specified list
list(field1, field2, field3) returns a list containing the named fields
listInRange(listField, minValue, maxValue) returns a list containing the elements in listField which are between minValue and maxValue (inclusive)
map() explained in greater detail below
now() returns the current time in milliseconds past the epoch
parentAccountId(accountId) returns the parent account id for the specified accountId
returns the accountId itself if there is no child
reverse(list) returns the specified list, reversed
round(val) returns the the numeric value val rounded to the nearest integer
returns null if val == null
returns error if val is non-numeric/non-null
split(s, sep) splits the string s into a list of strings using string sep as the field separator
startOfPeriod(periodName, timeStamp) returns the first timestamp in the period which includes the passed timestamp
period can be one of "hourly", "daily", "weekly", or "monthly"
startsWith(haystack, needle) returns true if the string haystack begins with the string needle
returns false if haystack is nil
sum(listValue) returns the sum of the items in the specified list, ignoring non-numeric elements

The map() function

Two parameter function

map(users, users.name)

When applied to the row

{
    "users": [{
        "id": 5,
        "name": "mickey"
    }, {
        "id": "2",
        "name": "minnie"
    }]
}

Example response

["mickey", "minnie"]

The map() function comes in two variants, which take either two or three parameters. The simpler form is map(listField, expression), and it applies the given expression to each item in the specified list, and returns a list of the results.

The listField must specify a list of objects. This means a list of integers will not work.

Three parameter function

map(x, names, len(x))

When applied to the row

{
"names": ["bugs", "daffy"]
}

Example response

[ 4, 5 ]

The three parameter form of map() is more general and works on lists of any type. While it works on any type, it’s important to note that it processes lists of objects slower than the two parameter form.

The first parameter is an identifier which the third parameter (the expression) can use to reference the particular value being mapped.

Both versions will return null if the list parameter is null.

Source specification

Definition

{
    "source": {
        "sourceType": {SOURCE PARAMS}
        "timeSeries": {
            "first": timeInMsOrExpression,
            "count": numberOfPeriods,
            "period": periodName
        }
      }
},

The source key must be specified as the first step in the pipeline unless spawn is used; then no source can exist. This tells the aggregation what data to feed into the pipeline.

Details
sourceType Source of data for the aggregation.

Row source specification

Think of row sources as tables, to borrow a term from relational databases. Once you understand what’s available in the row sources, you’ll be well on your way to knowing what’s possible overall.

When you return row source data, you can slice and dice it in a number of ways.

The short answer to “what can we access with the Pendo API” is: all the major entities, day/hour summaries for feature and page usage, and event level data for guide activity and polls.

The sourceType specifies what kind of data is being aggregated. Each specific type has specific parameters. If no parameters are provided, the empty {} can be replaced with null.

Row sources specify what types of rows should go into the pipeline, and are normally parameterized. The time period for the rows is not specified here; it is part of the time series specification instead.

Sources
accounts All accounts with their metadata. For customers using subaccounts, only the subaccounts are returned unless { "parentAccounts" : true } is specified, in which case only the parent accounts are returned.
accountTags Parameter may be { "tagId" : tagId } to limit results to a single accountTag. Returns { "accountId" : accountId , "accountTags": { tagId : true , ... }} for each account with the requested tag (listing only the requested tag), or if none specified, any currently valid accountTag (listing all tags on each).
events Returns summary data for all events on the system in a time period. Accepts an event class or list of event classes { "eventClass" : "ui"|"xhr"|"track"|["ui","track"] } to return, "ui" by default. Note: "ui" refers to events for both web and mobile.
featureEvents Covers all features unless featureId is provided to narrow the results to a single featureId. Returns results for requested time period. Accepts an event class or list of event classes { "eventClass" : "ui"|"xhr"|"track"|["ui","track"] } to return, "ui" by default. Note: "ui" refers to events for both web and mobile.
guideEvents Returns all guide events (guideSeen/dismissed/advanced) for requested time period. Can be limited by guideId or guideId and guideStepId.
guidesSeen Returns firstSeenAt, lastSeenAt, lastState, and seenCount for each visitor that saw the requested guide(s) in a time period. Parameter must be { "guideId" : guideId, "guideStepId" : guideStepId }; leaving out guide (blank/null/unsupplied) shows rows for all steps on all guides, and leaving out step shows all steps on the requested guide.
pageEvents Covers all pages unless pageId is provided to narrow the results to a single pageId. Returns results for requested time period. Accepts an event class or list of event classes { "eventClass" : "ui"|"xhr"|"track"|["ui","track"] } to return, "ui" by default. Note: "ui" refers to events for both web and mobile.
pollEvents Returns all poll responses for requested time period. Can be limited by guideId or guideId and pollId.
pollsSeen Returns poll responses in a time period. If visitor has multiple responses to the same poll, only the most recent is returned. Parameter must be { "guideId" : guideId, "pollId" : pollId }
trackEvents Returns one row for every Track Event for the requested time period. Accepted parameters include trackTypeId to drill down to a specific track type. You can use the expand pipeline operator to expose track type metadata (e.g. trackTypeId)
visitors All visitors with their metadata. Parameter may be { "identified" : true } to eliminate anonymous visitors
visitorTags Parameter may be { "tagId" : tagId } to limit results to a single visitorTag. Returns { "visitorId" : visitorId , "visitorTags": { tagId : true , ... }} for each visitor with the requested tag (listing only the requested tag), or if none specified, any currently valid visitorTag (listing all tags on each).

Blacklist Parameter

Definition (page events used as example)

{
    "source": {
        "pageEvents": {
            "pageId": "{pageId}",
            "blacklist": "ignore"
        }
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"pageEvents":{"pageId":"aJ0KOADQZVL5h9zQhiQ0q26PNTM","blacklist":"ignore"},"timeSeries":{"first":"1506977216000","count":-5,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"pageEvents\":{\"pageId\":\"aJ0KOADQZVL5h9zQhiQ0q26PNTM\",\"blacklist\":\"ignore\"},\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-5,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json",
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "results": [{
            "accountId": "Kappa Trust",
            "visitorId": "59",
            "numEvents": 1,
            "numMinutes": 1,
            "server": "www.pendosandbox.com",
            "remoteIp": "59.89.251.103",
            "parameters": null,
            "userAgent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
            "day": 1506830400000,
            "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM"
        }
    ]
}

All row sources take an optional blacklist parameter in addition to any listed above. For example, on the right you’ll see an example where we examine all of the page events for a particular pageId, ignoring blacklist.

Details
apply Default everywhere, and filters output according to blacklist rules
only Outputs only those rows that match the blacklist
ignore Returns all rows, ignoring the blacklist

Time Series

Example time series for July 10, 2015 through July 12, 2015

{
    "timeSeries": {
        "period": "dayRange",
        "first": 1436553419000,
        "count": 3
    }
}

Example time series for three hours ago to (and including) the current hour.

{
    "timeSeries": {
        "period": "hourRange",
        "first": "now() - 3 * 60*60*1000",
        "last": "now()"
    }
}

The timeSeries consists of the length of each time period and a timestamp for the first period in milliseconds since the epoch. If first is a string it will be evaluated as an expression to derive a timestamp.

It also requires either a count of the number of periods to include in the aggregation or an expression which evaluates to the last time period to include in the aggregation.

Details
period dayRange or hourRange
first The timestamp in milliseconds after the epoch for the start of period.
count Number of periods to include in the aggregation

Full time periods are always evaluated. Even if the first time does not coincide with the beginning of a period, all of the data for the period which contains time first will be used.

For the dayRange period, the day aligns with the time zone for that pendo account. This does mean that there will occasionally by dayRange periods which include 23 or 25 hours of data because of the switch to and from daylight savings time. If this is undesirable, hourRange may be used, though there will be a significant performance impact when large amounts of data are being evaluated.

Events - grouped

The following row sources require a date range (relative or absolute) and period (day). They return a row of data for each unique combination of day/hour, visitorId, accountId, server name, and IP address.

Attributes
events All recorded click and pageview events (tagged or untagged)
featureEvents All recorded click events matching tagged features
pageEvents All recorded pageviews matching tagged pages
trackEvents All recorded trackEvents

All grouped event sources can be sent with a details query param set to true. If this query param is set, then a details object will be returned in the response, unless no details are present.

Details Attributes
validThrough An object whose keys represent the Pendo application ID and whose value is a timestamp that indicates when data was last processed

Example response

{
    "results": [{
        "accountId": "Kappa Trust",
        "visitorId": "59",
        "numEvents": 12,
        "numMinutes": 1,
        "server": "www.pendosandbox.com",
        "remoteIp": "59.89.251.103",
        "parameters": null,
        "userAgent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
        "day": 1506830400000,
        "pageId": "allevents"
    }],
    "startTime": 1504324800000,
    "details": {
       "validThrough": {
           "-323232": 1573772400000,
           "5629499534213000": 1573774550451,
           "5629499534213111": 1573774550451,
           "5629499534213120": 1573772400000
       }
    }
}

The events row source

Definition

{
    "source": {
        "events": null,
        "timeSeries": {
            "first": "{timeInMsOrExpression}",
            "count": "{numberOfPeriods}",
            "period": "{periodName}"
        }
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"events":null,"timeSeries":{"first":"1506977216000","count":-30,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"events\":null,\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-30,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "results": [{
        "accountId": "Kappa Trust",
        "visitorId": "59",
        "numEvents": 12,
        "numMinutes": 1,
        "server": "www.pendosandbox.com",
        "remoteIp": "59.89.251.103",
        "parameters": null,
        "userAgent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
        "day": 1506830400000,
        "pageId": "allevents"
    }],
    "startTime": 1504324800000
}
  • Returns a row for each unique combination of day/hour, visitorId, accountId, server name, IP address, and user agent.
  • Encompasses all events, whether tagged or untagged (note the pageId “allevents”)
  • Useful for measuring total time, days active, etc.
  • Optionally pass an eventClass of "track" or ["track","ui] to specify which event bucket(s) to return. eventClass is "ui" by default.

The featureEvents row source

Definition

{
    "source": {
        "featureEvents": {
            "featureId": "{featureId}"
        },
    "timeSeries": {
            "first": "{timeInMsOrExpression}",
            "count": "{numberOfPeriods}",
            "period": "{periodName}"
        }
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"featureEvents":{"featureId":"OFjRasLtgMG8_74hpiXdzVD7PH8"},"timeSeries":{"first":"1506977216000","count":-30,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"featureEvents\":{\"featureId\":\"OFjRasLtgMG8_74hpiXdzVD7PH8\"},\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-30,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "results": [{
            "accountId": "Delta Inc",
            "visitorId": "3",
            "numEvents": 1,
            "numMinutes": 1,
            "server": "www.pendosandbox.com",
            "remoteIp": "103.63.15.48",
            "parameters": null,
            "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
            "day": 1506571200000,
            "featureId": "OFjRasLtgMG8_74hpiXdzVD7PH8"
        }
    ]
}
  • Includes events which can be matched to tagged feature rules
  • Returns a row for each unique combination of feature ID, day/hour, visitorId, accountId, server name, IP address, and user agent.
  • Accepted parameters are null for all feature data or featureId:FEATURE_ID for a specific feature.
  • Remember expand if you need additional feature data

The pageEvents row source

Definition

{
    "source": {
        "pageEvents": {
            "pageId": "{pageId}"
        },
    "timeSeries": {
            "first": "{timeInMsOrExpression}",
            "count": "{numberOfPeriods}",
            "period": "{periodName}"
        }
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"pageEvents":{"pageId":"aJ0KOADQZVL5h9zQhiQ0q26PNTM"},"timeSeries":{"first":"1506977216000","count":-30,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"pageEvents\":{\"pageId\":\"aJ0KOADQZVL5h9zQhiQ0q26PNTM\"},\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-30,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "results": [{
            "accountId": "Acme Corp",
            "visitorId": "10",
            "numEvents": 1,
            "numMinutes": 1,
            "server": "www.pendosandbox.com",
            "remoteIp": "110.227.245.175",
            "parameters": null,
            "userAgent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
            "day": 1506484800000,
            "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM"
        }
    ]
}
  • Includes events which can be matched to tagged page rules
  • Returns a row for each unique combination of page ID, day/hour, visitorId, accountId, server name, IP address, and user agent.
  • Accepted parameters are null for all page data or pageId:PAGE_ID for a specific page.
  • Remember expand if you need additional page data

The trackEvents row source

Definition

{
  "source": {
        "trackEvents": {
            "trackTypeId": "{trackTypeId}"
        },
    "timeSeries": {
            "first": "{timeInMsOrExpression}",
            "count": "{numberOfPeriods}",
            "period": "{periodName}"
        }
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"trackEvents":{"trackTypeId":"{trackTypeId}"},"timeSeries":{"first":"1506977216000","count":-30,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"trackEvents\":{\"trackTypeId\":\"{trackTypeId}\"},\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-30,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

  "results": [{

        "accountId": "Delta Inc",
        "visitorId": "DeltaTest",
        "numEvents": 1,
        "numMinutes": 1,
        "server": "app.pendo.io",
        "remoteIp": "66.57.183.10",
        "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
        "properties": {
            "android": false,
            "any": false,
            "apple": false,
            "phone": false,
            "table": false
            },
        "day": 1560398400000,
        "appId": -323232,
        "trackTypeId": "0cj4FjvYdHW4RAdN3_-zbmz_6C8"

      }]
  • Returns one row for every track event that occurs in a given time period
  • Accepted parameters include trackTypeId to drill down to a specific track type
  • You can use the expand pipeline operator to see track type metadata (e.g. trackTypeId)

Events - ungrouped

For some events, we expose ungrouped events. These are visible for a specified time period.

Sources
guideEvents Interactions your visitors have with guides
guidesSeen Summary of when visitors see guides
guidesSeenEver Summary of when visitors see guides
pollEvents Interactions your visitors have with polls
pollsSeen Summary of when and how visitors respond to polls
pollsSeenEver Summary of when and how visitors respond to polls

The guideEvents row source

Definition

{
    "source": {
        "guideEvents": null,
    "timeSeries": {
            "first": "{timeInMsOrExpression}",
            "count": "{numberOfPeriods}",
            "period": "{periodName}"
        }
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"guideEvents":null,"timeSeries":{"first":"1506977216000","count":-10,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"guideEvents\":null,\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-10,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "accountIds": [
        "Acme"
    ],
    "browserTime": 1462796392383,
    "country": "US",
    "type": "guideAdvanced",
    "guideId": "He3BLNt44i0xwO5AEJVIijEswro",
    "guideStepId": "4TaMV6TLY1JmKIFkprqOcQllU8k",
    "latitude": 35.823483,
    "loadTime": 0,
    "longitude": -78.825562,
    "region": "nc",
    "remoteIp": "209.136.209.34",
    "serverName": "your.app.com",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17",
    "visitorId": "[email protected]",
    "accountId": "Acme"
}
  • Returns one event row for every guide event that occurs. This is not a summary or bucket structure like previous examples.
  • Type field values include guideAdvanced, guideSeen, and guideDismissed
  • Accepted parameters include guideId and guideStepId to drill down into a specific guide or step.
  • pollEvents behaves similiarly and provides one row for every poll response that occurs. You can specify pollId as a parameter to that source.

The guideSeen row source

Definition

{
    "source": {
        "guidesSeen": {
            "guideId": "{guideId}",
            "guideStepId": "{guideStepId}"
        },
    "timeSeries": {
            "first": "{timeInMsOrExpression}",
            "count": "{numberOfPeriods}",
            "period": "{periodName}"
        }
    }
}

Exmaple request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"guidesSeen":{"guideId":"nWtgylnMqWeB4DynO5duF9ako-M","guideStepId":"mHO55y6WJvJ0CnsmUgAtiGtgobA"},"timeSeries":{"first":"1506977216000","count":-10,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"guidesSeen\":{\"guideId\":\"nWtgylnMqWeB4DynO5duF9ako-M\",\"guideStepId\":\"mHO55y6WJvJ0CnsmUgAtiGtgobA\"},\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-10,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "firstSeenAt": 1489673759222,
    "guideId": "nWtgylnMqWeB4DynO5duF9ako-M",
    "guideStepId": "mHO55y6WJvJ0CnsmUgAtiGtgobA",
    "lastAdvancedAutoAt": 0,
    "lastDismissedAutoAt": 0,
    "lastSeenAt": 1489674347693,
    "lastState": "advanced",
    "seenCount": 5,
    "visitorId": "avery"
}
  • Returns a row for each unique combination of Visitor ID, guide ID, and step ID
  • You can additionally supply guideId and guideStepId to drill into a specific guide or step.
  • The guidesSeenEver row source can also be used for the same output, but is time insensitive and does not require a timeSeries.

The pollEvents row source

Definition

{
    "source": {
        "pollEvents": null,
    "timeSeries": {
            "first": "{timeInMsOrExpression}",
            "count": "{numberOfPeriods}",
            "period": "{periodName}"
        }
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"pollEvents":null,"timeSeries":{"first":"1506977216000","count":-10,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"pollEvents\":null,\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-10,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "accountIds": [
        "Acme"
    ],
    "browserTime": 1462796392383,
    "country": "US",
    "type": "pollResponse",
    "guideId": "He3BLNt44i0xwO5A201IijEswro",
    "latitude": 35.823483,
    "loadTime": 0,
    "longitude": -78.825562,
    "pollId": "z7y94y62v3c",
    "region": "nc",
    "remoteIp": "209.136.209.34",
    "serverName": "your.app.com",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
    "visitorId": "[email protected]",
    "accountId": "Acme",
    "pollResponse": "You guys rock!"
}
  • Returns one row for every poll response that occurs.
  • Accepted parameters include guideId and pollId to drill down into a specific poll.

The pollsSeen row source

Definition

{
    "source": {
        "pollsSeen": {
            "guideId": "{guideId}",
            "pollId": "{pollId}"
        },
    "timeSeries": {
            "first": "{timeInMsOrExpression}",
            "count": "{numberOfPeriods}",
            "period": "{periodName}"
        }
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"pollsSeen":{"guideId":"1wz09ZEAFp-HVl78Iw8oxpwbRZA","pollId":"3isny1qp7t2"},"timeSeries":{"first":"1506977216000","count":-10,"period":"dayRange"}}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"pollsSeen\":{\"guideId\":\"1wz09ZEAFp-HVl78Iw8oxpwbRZA\",\"pollId\":\"3isny1qp7t2\"},\"timeSeries\":{\"first\":\"1506977216000\",\"count\":-10,\"period\":\"dayRange\"}}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "accountId": "1",
    "guideId": "1wz09ZEAFp-HVl78Iw8oxpwbRZA",
    "pollId": "3isny1qp7t2",
    "response": 0,
    "time": 1500305598629,
    "visitorId": "1"
}
  • Returns poll responses in a time period
  • Only the most recent poll response for a visitor is displayed i.e. if a visitor has responded to the same poll multiple times, pollsSeen will only return most recent response. To return all responses, use pollEvents.
  • You must supply guideId and pollId as parameters to drill into specific poll events
  • The pollsSeenEver row source can also be used for the same output, but is time insensitive and does not require a timeSeries.

Entities

Entities are the nouns of Pendo. They appear in the left-nav of our UI.

Entities
accounts The accounts your users belong to (in most cases your customers)
features Sets of rules that identify individual product features (defined by a DOM rule)
guides In-app messages you show your visitors
pages Sets of rules that identify individual pages in your product (defined by a URL rule)
trackTypes Types created by sending Track Events via server side, client side or Segment.com
visitors Your product’s users (including internal users who access customer accounts)

The accounts row source

Definition syntax

{
    "source": {
        "accounts": null
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"accounts":null}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"accounts\":null}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "results": [{
            "accountId": "Iota Partners",
            "metadata": {
                "agent": {},
                "auto": {
                    "firstvisit": 1506520495929,
                    "id": "Iota Partners",
                    "idhash": 3996782207,
                    "lastupdated": 1506969364496,
                    "lastvisit": 1506969364036
                }
            }
        }
    ]
}

The accounts source is the analogue of the visitors source. It returns one row per account ever seen and has various metadata on the account. Each account has a unique accountId defined by you through the installation snippet.

For customers using subaccounts, only the subaccounts are returned unless { "parentAccounts" : true } is specified as a parameter, in which case only the parent accounts are returned.

Definition using expand

[{
        "source": {
            "accounts": null
        }

    },
    {
        "expand": {
            "account": {
                "account": "accountId"
            }
        }
    }
]

Account data can also be accessed using the expand pipeline map operator. This is handy for including account data when using other sources (e.g. featureEvents and pageEvents sources).

The features row source

Definition

{
    "source": {
        "features": null
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"features":null}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"features\":null}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "results": [{
            "color": "gray",
            "createdAt": 1505938327432,
            "createdByUser": {
                "first": "Adam",
                "id": "5197072786522112",
                "last": "Lohner",
                "role": 8,
                "username": "[email protected]"
            },
            "dirty": false,
            "elementPathRules": [
                "a:contains('Data Presentation')"
            ],
            "group": {
                "color": ".groupColor01",
                "createdAt": 1505937447295,
                "createdByUser": {
                    "first": "",
                    "id": "",
                    "last": "",
                    "role": 0,
                    "username": ""
                },
                "description": "",
                "id": "_PENDO_DEFAULTGROUP_01_",
                "items": [],
                "lastUpdatedAt": 1505938327653,
                "lastUpdatedByUser": {
                    "first": "Adam",
                    "id": "5197072786522112",
                    "last": "Lohner",
                    "role": 8,
                    "username": "[email protected]"
                },
                "length": 6,
                "name": "Dashboard"
            },
            "id": "UB9RTn0B9esKqPW_NcfB25n3QAc",
            "kind": "Feature",
            "lastUpdatedAt": 1505938327432,
            "lastUpdatedByUser": {
                "first": "Adam",
                "id": "5197072786522112",
                "last": "Lohner",
                "role": 8,
                "username": "[email protected]"
            },
            "name": "Data Presentation Toggle Dropdown",
            "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
            "rootVersionId": "UB9RTn0B9esKqPW_NcfB25n3QAc",
            "stableVersionId": "UB9RTn0B9esKqPW_NcfB25n3QAc-20170920201207.432160413",
            "validThrough": 1506974400000
        }
    ]
}

Tagged features. Returns one row for each tagged feature.

Definition using expand

[{
        "source": {
            "accounts": null
        }

    },
  {
    "expand": {
      "feature": {
        "feature": "featureId"
      }
    }
  }
]

Although features can be accessed directly as a source, for convenience we recommend accessing feature entity data using the expand pipeline map operator. This is handy for including additional feature data when using other sources (like featureEvents).

The guides row source

Definition

{
    "source": {
        "guides": null
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"guides":null}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"guides\":null}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "attributes": { ... },
    "audience": [ ... ],
    "createdAt": 1440449676899,
    "createdByUser": {
        "first": "Someone",
        "id": "5269565705551872",
        "last": "Lastname",
        "role": 8,
        "username": "[email protected]"
    },
    "expiresAfter": 1440472740000,
    "id": "BF_p40WvYWC2o81pvsdt1kjcIkI",
    "isMultiStep": false,
    "lastUpdatedAt": 1460734696429,
    "lastUpdatedByUser": {
        "first": "",
        "id": "4985730428305408",
        "last": "",
        "role": 8,
        "username": "[email protected]"
    },
    "launchMethod": "auto",
    "name": "2015-08-24 - Maintenance tonight.",
    "state": "disabled",
    "stateHistory": [ ... ],
    "steps": [{
        "advanceMethod": "button",
        "attributes": {
            "height": 395,
            "width": 440
        },
        "content": "",
        "createdByUser": {
            "first": "Someone",
            "id": "5269565705551872",
            "last": "Lastname",
            "role": 8,
            "username": "[email protected]"
        },
        "elementPathRule": "",
        "guideId": "BF_p40WvYWC2o81pvsdt1kjcIkI",
        "id": "Itfe6aDRNtgx9J1XisQwaCxDS-A",
        "lastUpdatedAt": 1460734696429,
        "lastUpdatedByUser": {
            "first": "",
            "id": "4985730428305408",
            "last": "",
            "role": 8,
            "username": "[email protected]"
        },
        "name": "",
        "rank": 5000000,
        "resetAt": 0,
        "thumbnailUrls": [
            "https://storage.googleapis.com/pendo-static-5668600916475904/b4fab315-ab24-4e95-6ffe-fcbb19267fdd"
        ],
        "type": "lightbox"
    }]
}

steps include a single item for lightboxes, tooltips, banners, etc. and multiple items for walkthroughs.

The pages row source

Definition

{
    "source": {
        "pages": null
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"pages":null}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"pages\":null}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "results": [{
        "color": "gray",
        "createdAt": 1505938241596,
        "createdByUser": {
            "first": "Adam",
            "id": "5197072786522112",
            "last": "Lohner",
            "role": 8,
            "username": "[email protected]"
        },
        "dirty": false,
        "group": {
            "color": ".groupColor01",
            "createdAt": 1505937447295,
            "createdByUser": {
                "first": "",
                "id": "",
                "last": "",
                "role": 0,
                "username": ""
            },
            "description": "",
            "id": "_PENDO_DEFAULTGROUP_01_",
            "items": [],
            "lastUpdatedAt": 1505938327653,
            "lastUpdatedByUser": {
                "first": "Adam",
                "id": "5197072786522112",
                "last": "Lohner",
                "role": 8,
                "username": "[email protected]"
            },
            "length": 6,
            "name": "Dashboard"
        },
        "id": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
        "kind": "Page",
        "lastUpdatedAt": 1505938241596,
        "lastUpdatedByUser": {
            "first": "Adam",
            "id": "5197072786522112",
            "last": "Lohner",
            "role": 8,
            "username": "[email protected]"
        },
        "name": "Dashboard",
        "rootVersionId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
        "rules": [{
            "designerHint": "http://pendosandbox.com/",
            "parsedRule": "^https?://[^/]*/?(?:;[^#]*)?(?:\\?[^#]*)?(?:#.*)?$",
            "rule": "//*"
        }],
        "rulesjson": "",
        "stableVersionId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM-20170920201041.596687476",
        "validThrough": 1506981600000
    }]
}

Tagged features. Returns one row for each tagged feature.

Definition using expand

[{
        "source": {
            "pages": null
        }
    },
    {
        "expand": {
            "page": {
                "page": "pageId"
            }
        }
    }
]

Although pages can be accessed directly as a source, for convenience we recommend accessing page entity data using the expand pipeline map operator. This is handy for including page data when using other sources (like pageEvents).

The trackTypes row source

Definition

{
  "source": {
        "trackTypes": null
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"trackType":null}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"trackTypes\":null}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

"results": [{
        "appId": -323232,
        "color": "",
        "createdAt": 1560447086076,
        "createdByUser": {
            "first": "System",
            "id": "-42",
            "last": "User",
            "role": 0,
            "userType": "normal",
            "username": "--system-user--"
        },
        "dirty": false,
        "group": {
            "color": "",
            "description": "",
            "id": "",
            "items": null,
            "length": 0,
            "name": ""
        },
        "id": "0cj4FjvYdHW4RAdN3_-zbmz_6C8",
        "kind": "TrackType",
        "lastUpdatedAt": 1560447086076,
        "lastUpdatedByUser": {
            "first": "System",
            "id": "-42",
            "last": "User",
            "role": 0,
            "userType": "normal",
            "username": "--system-user--"
        },
        "name": "isMobile",
        "rootVersionId": "0cj4FjvYdHW4RAdN3_-zbmz_6C8",
        "stableVersionId": "0cj4FjvYdHW4RAdN3_-zbmz_6C8-20190613173126.076646151",
        "trackTypeName": "isMobile",
        "trackTypeRules": [
            "isMobile"
        ],
        "validThrough": 1562608800000
    }
    ]

Definition using expand

[{
        "source": {
            "accounts": null
        }
    },
  {
    "expand": {
      "trackTypes": {
        "trackTypeId": "{trackTypeId}"
      }
    }
  }
]

The trackTypes source returns one row per track type that are "ever seen" and not deleted. Each track type has a trackTypeName defined by you in the track event submission via server side, client side or Segment.com. The unique id is generated upon submission of the first track event type.

Although track types can be accessed directly as a source, for convenience we recommend accessing track type entity data using the expand pipeline map operator. (e.g. trackEvents).

Visitors

Definition

{
    "source": {
        "visitors": null
    }
}

Example request

curl -X POST \
  https://app.pendo.io/api/v1/aggregation \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: [add_your_pendo_int_key_here]' \
  -d '{"response":{"mimeType":"application/json"},"request":{"pipeline":[{"source":{"visitors":null}}]}}'
import requests
url = "https://app.pendo.io/api/v1/aggregation"
data = "{\"response\":{\"mimeType\":\"application/json\"},\"request\":{\"pipeline\":[{\"source\":{\"visitors\":null}}]}}"
headers = {
    'x-pendo-integration-key': "[add_your_pendo_int_key_here]",
    'content-type': "application/json"
}
response = requests.post(url, data = data, headers = headers)

Example response

{
    "results": [{
        "metadata": {
            "agent": {
                "email": "[email protected]",
                "ipaddress": "184.169.45.4",
                "language": "en_US"
            },
            "auto": {
                "accountid": "Epsilon united",
                "accountids": [
                    "Epsilon united"
                ],
                "firstvisit": 1506965912312,
                "id": "84",
                "idhash": 2012371633,
                "lastbrowsername": "Chrome",
                "lastbrowserversion": "61.0.3163",
                "lastoperatingsystem": "Mac OS X",
                "lastservername": "pendosandbox.com",
                "lastupdated": 1506976690418,
                "lastuseragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
                "lastvisit": 1506976690112,
                "nid": 84
            }
        },
        "visitorId": "84"
    }]
}

The visitors source returns one row per visitor ever seen and contains various metadata about the visitor. Each visitor has a unique visitorId that is defined by you and passed to Pendo through your installation snippet.

A visitor may be identified (a visitor ID is passed through the installation snippet) or anonymous (an ID is not passed to Pendo so we generate one for the visitor that is prepended with _PENDO_T_).

Accepted parameters are null or {"identified":true} to eliminate anonymous visitors.

Metadata
agent data supplied by the Pendo javascript widget
auto data automatically calculated, and summarized by Pendo
custom custom field data
salesforce data synced from Salesforce
segment data synced from Segment

Definition using expand

[{
        "source": {
            "pages": null
        }
    },
    {
        "expand": {
            "visitor": {
                "visitor": "visitorId"
            }
        }
    }
]

Visitor data can also be accessed using the expand pipeline map operator. This is handy for including visitor data when using other sources (e.g. featureEvents and pageEvents sources).

Pipeline

Example sytnax #1

{
    "cat": null
}

Example sytnax #2

{
    "field": "firstName",
    "operator": "==",
    "value": "John"
}

Each step is of the form { "name" : parameterObject }.

The source rows are transformed into result rows by the pipeline; the final rows are the result of the aggregation step. Pipelines can be arbitrarily long, and are represented as an ordered list of individual steps.

Operators

Operators
cat Takes no parameters, and returns each row without changing it.
count Counts the number of input rows and returns a single row of the form { "count" : 456 }
accumulate Keeps a running total of more than one field, and includes the current value of the total in each row. Parameters are of the forum { "totalField1" : "sourceField1" }
eval Inserts new fields based on one or more expressions. Format is an { "fieldName1" : "expression" }
identified Eliminates rows whose named field looks like an anonymous visitorId { "identified" : "visitorId" } where visitorId is the field name to check.
limit Returns the first N rows and discards the rest { "limit" : 5 }
select Builds a new row (while discarding the old one) containing one or more fields. Format is an { "fieldName1" : "expression" }
set Sets fields to constant values { "set" : { "field1" : 5, "field2.nested" : 20 } }
sort Sorts the rows by the specified field list { "sort" : [ "fieldName", "anotherFieldName" ] } Prepend a - to the front of a field name to reverse sort by that field.
unmarshal Expands an embedded JSON string into sub-objects.
useragent Expands a user agent string into a parsed set of strings.

The spawn operation

Definition

{
    "spawn": [
        [{
                "source": {
                    "events": null,
                    "timeSeries ": {
                        "period": "dayRange",
                        "first": 1404745200000,
                        "count": 7
                    }
                }
            },
            {
                "cat": null
            }
        ],
        [{
                "source": {
                    "events": null,
                    "timeSeries ": {
                        "period": "month",
                        "first": 1404745200000,
                        "count": 7
                    }
                }
            },
            {
                "count": null
            }
        ]
    ]
}

The spawn operator behaves like fork, but each nested pipeline must specify its own source. This allows multiple sources to be used to create a single stream of rows which are processed by the remainder of the pipe.

Only sources which cause a single pipeline to be instantiated may be used; this means dayRange, hourRange, or any source whose count is 1 is available.

The timeSeries for the source is part of the source specification for the spawn pipeline.

The switch operation

Definition

{
    "switch": {
        "newField": {
            "existingField": [{
                    "value": "small",
                    "<": 10
                },
                {
                    "value": "medium",
                    ">=": 10,
                    "<": 20
                },
                {
                    "value": "large",
                    ">=": 20,
                    "<": 50
                }
            ]
        }
    }
}

The switch operation allows a field to checked against any number of conditions, and have a new field set in the row based on which condition the original field matches.

For each row the existingField will be checked to see which set of conditions its value matches.

It must match all of the conditions for newField to be set to the value indicated. If no conditions match, or if existingField is not set at all, the row is skipped.

For the above input, the row { "existingField" : 15 } will become { "existingField" : 15, "newField" : "medium" }

The filter operation

Definition

{
    "filter": "fieldName == 5 || len(anotherField) > 3"
}

The filter pipeline operator evaluates an expression and eliminates rows that for which the expression is false.

The fork operation

The following calculates the total time for each accountId and visitorId

{
    "fork": [
        [{
            "group": {
                "group": [
                    "visitorId"
                ],
                "fields": [{
                    "time": {
                        "sum": "numMinutes"
                    }
                }]
            }
        }],
        [{
            "group": {
                "group": [
                    "accountId"
                ],
                "fields": [{
                    "time": {
                        "sum": "numMinutes"
                    }
                }]
            }
        }]
    ]
}

The fork operator allows the pipeline to be split into multiple pipelines, with each of the child pipelines receiving all of the rows for that step.

Note that the same row is sent to all of the child pipelines; it is not a copy of the row and any changes to the row made in one pipeline will be visible in all pipelines.

The rows which result from each pipeline are all sent through the remainder of the parent pipeline. Forks may be nested, however this has not been well-tested (aka - no promises).

Empty pipelines (which would pass through the rows without modifying them) are not permitted, but a pipeline with a single cat operation performs identically.

The join operation

Definition

{
    "join": {
        "fields": [
            "firstName",
            "lastNme"
        ],
        "width": 3
    }
}

The join operator merges multiple rows together based on one or more keys. If there are field conflicts, the values from rows encountered later in the join will win. The optional width argument allows the user to tell join how many rows are expected to make up the final result. Once that many rows with the same join key have been seen, the merged row is passed to the next operation in the pipeline. If more rows are later seen with that join key, they are treated as a new join operation. Any join keys which have had less than width rows are processed once all input rows have been seen.

The group operation

Example request to calculate how much time each identified visitor has spent on the site over 30 days

{
    "response": {
        "location": "request",
        "mimeType": "application/json"
    },
    "request": {
        "pipeline": [
            {
                "source": {
                    "events": null,
                    "timeSeries": {
                        "count": -30,
                        "first": "1572580800000",
                        "period": "dayRange"
                    }
                }
            },
            {
                "identified": "visitorId"
            },
            {
                "group": {
                    "group": [
                        "visitorId"
                    ],
                    "fields": {
                        "minutes": {
                            "sum": "numMinutes"
                        }
                    }
                }
            }
        ]
    },
    "requestId": "last30days"
}

The group operator supports flexible grouping (similar to GROUP BY in SQL) and simple aggregations of fields. It supports the following parameters:

Parameters
group List of fields whose values match in each grouping
fields Set of fields whose values are aggregated across the group
stringSort Result rows will be sorted by the group key. The group key is treated as a string for sort purposes (so "2" > "10"). This provides a stable ordering for the result.

Each resulting row consists of all of the fields specified by both the group and fields specification.

Aggregation fields consist of field name to use in the output row, an aggregation name, and a field name from the input row. For example, to count the rows in a group use { "outputField" : { "count" : "inputField" } } will count the number of rows which match (here the field name must be specified, but is irrelevant). The following row aggregators are supported:

Aggregators
count Counts the number of rows in the group. If a field name is it counts the unique occurrences of that field.
listAverage Average the individual values in a list arguement and return a list of those averages.
max Returns the largest value of the specified (numeric) field.
min Returns the smallest value of the specified (numeric) field.
sum Adds up the values of the specified field.
first Returns the first value of the specified field (note: "first" is only defined as deterministically as the input order is).

Count the number of unique visitorIds use the following pipeline:

[{
        "group": {
            "group": [
                "visitorId"
            ]
        }
    },
    {
        "visitorCount": {
            "count": null
        }
    }
]

To get the number of events for each visitorIduse:

[{
    "group": {
        "group": [
            "visitorId"
        ],
        "fields": {
            "eventCount": {
                "count": "event"
            }
        }
    }
}]

The reduce operation

Count the number of rows and add up the minutes fields in the rows:

[{
    "reduce": {
        "eventCount": {
            "count": null
        },
        "totalMinutes": {
            "sum": "numMinutes"
        }
    }
}]

The reduce operator collects all rows into a single row, and performs aggregations on fields. The aggregators and format are identical to the fields parameter for the group pipeline operation.

Example request to calculate the total number of events and the total number of minutes for a thirty day period.

{
    "requestId": "last30DaysEventAndMinuteTotals",
    "timeSeries": {
        "period": "dayRange",
        "count": 30,
        "first": 1404745200000
    },
    "source": {
        "events": null
    },
    "pipeline": [{
        "reduce": [{
                "events": {
                    "sum": "numEvents"
                }
            },
            {
                "minutes": {
                    "sum": "numMinutes"
                }
            }
        ]
    }]
}

Count the number of unique visitors and accounts in a dataset

{
    "requestId": "numberOfUniqueAccountsAndVisitors",
    "timeSeries": {
        "period": "dayRange",
        "count": 30,
        "first": 1404745200000
    },
    "source": {
        "events": null
    },
    "pipeline": [{
        "reduce": [{
            "reduce": {
                "visitors": {
                    "count": "visitorId"
                },
                "accounts": {
                    "count": "accountId"
                }
            }
        }]
    }]
}

Example request using group and reduce to count the number of visitors in a set of events and the total number of minutes used by those visitor:

{
    "requestId": "lastDaysEventAndMinuteTotals",
    "timeSeries": {
        "period": "dayRange",
        "count": 30,
        "first": 1404745200000
    },
    "source": {
        "events": null
    },
    "pipeline": [{
        "group": {
            "group": [
                "visitorId"
            ],
            "fields": {
                "visitorMinutes": {
                    "sum": "numMinutes"
                }
            }
        },
        "reduce": {
            "visitorCount": {
                "count": "numVisitors"
            },
            "totalMinutes": {
                "sum": "visitorMinutes"
            }
        }
    }]
}

The segment operation

Definition

{
    "segment": {
        "id": "id"
    }
}

Segments are used to preselect groups of visitors or accounts. Preexisting segments filter rows via the segment operator.

An input row is passed if the accountId and visitorId in the input row match an item in the segment. Some segments may specify only visitors or accounts; in those cases the segment operator will only match against the appropriate field from the input row.

The expand operation

Expand visitors into a subdocument called info

{
    "expand": {
        "info": {
            "visitor": "visitorId"
        }
    }
}

NOTE: The implementation of expand is not well optimized and should not be used for large numbers of expansions. See bulkExpand below. The expand operator does as its name implies - it expands fields into subdocuments based on an id. The step is of the following form: { expand : { outputFieldName : { dataType : idFieldName } } }.

The following data types support expand: page, feature, account, and visitor.

The bulkExpand operation

The bulkExpand operator behaves identically to expand, but is optimized for large numbers of visitors and accounts.

The following data types support expand: account and visitor.

The unwind operation

To unwind the following:

{
    "name": "fred",
    "items": [{
            "v": "first"
        },
        {
            "v": "second"
        },
        {
            "v": "third"
        }
    ]
}

Try:

{
    "unwind": {
        "field": "items",
        "index": "itemIndex"
    }
}

Response would yield:

{
    "name": "fred",
    "items": {
        "v": "first"
    },
    "itemIndex": 0
} {
    "name": "fred",
    "items": {
        "v": "second"
    },
    "itemIndex": 1
} {
    "name": "fred",
    "items": {
        "v": "third"
    },
    "itemIndex": 2
}

The unwind operator expands a list of items into separate rows. All other items are preserved, and an index may optionally be added.

Add "prefix" : true and you will get:

[{
    "name": "fred",
    "items": [{
        "v": "first"
    }],
    "itemIndex": 0
}, {
    "name": "fred",
    "items": [{
        "v": "first"
    }, {
        "v": "second"
    }],
    "itemIndex": 1
}, {
    "name": "fred",
    "items": [{
        "v": "first"
    }, {
        "v": "second"
    }, {
        "v": "third"
    }],
    "itemIndex": 2
}]

Alternatively, if everything to the left of each items is important, unwind can preserve those items.

If the list to unwind is empty then no rows will be emitted unless { "keepEmpty" : true } is specified, in which case the original row will be preserved.

The useragent operation

Definition

{
    "useragent": {
        "output": "input"
    }
}

The useragent operation parses the user agent string in the field input and renders it into a object in output.

Output
name the browser’s name (e.g. "MSIE", "Chrome", etc.)
version the version of the browser
os the operating system (e.g. "Windows", "Mac OS X", "GNU/Linux", etc.)
type the type of user agent (e.g. "Browser", "Crawler", etc.)

Multi-App

Using the pages source as an example, without multi-app the source looks like this:

{
      "source": {
          "pages": null
                }
    }

Multi-App is a relatively new feature Pendo offers that enables provisioning of Pendo application snippets for more than one application associated with a single Pendo subscription.

To execute Aggregations specific to an app in a multi-app context, you’ll need to change the source value within the aggregation from null - which is an indicator to return all records for all apps associated with the sub - to include an appId value.

Including the appId scopes the results to the data associated with just that application within the subscription.

For all multi-app Aggregations, use the primary app’s Integration API key for the value for x-pendo-integration-key in the Header.

appId

With multi-app source will look like this:

{
      "source": {
          "pages": {
              "appId": 5629499534213120
                   }
                }
   }

appId can be found by navigating to Settings -> Subscription Settings then clicking on View App Details for the specific app you want to query.

The appId is present in the URL after you navigate to the app from Subscription Settings.

The first app associated with the subscription will always have the appId value -323232. For example, https://app.pendo.io/admin/app/-323232.

All other apps will have a system generated value. For example, in this URL https://app.pendo.io/admin/app/5629499534213120 the appId is 5629499534213120

Feature

Feature endpoint

https://app.pendo.io/api/v1/feature

The {featureId} referenced below can be found at the end of the URL when viewing details for a specific feature within the app. You can view a comprehensive list of all tagged features here.

The feature object

Example response

[{
        "createdByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "createdAt": 1505938327432,
        "lastUpdatedByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "lastUpdatedAt": 1505938327432,
        "kind": "Feature",
        "rootVersionId": "UB9RTn0B9esKqPW_NcfB25n3QAc",
        "stableVersionId": "UB9RTn0B9esKqPW_NcfB25n3QAc-20170920201207.432160413",
        "id": "UB9RTn0B9esKqPW_NcfB25n3QAc",
        "name": "Data Presentation Toggle Dropdown",
        "color": "gray",
        "group": {
            "id": "_PENDO_DEFAULTGROUP_01_",
            "name": "Dashboard",
            "description": "",
            "color": ".groupColor01",
            "length": 6,
            "items": [],
            "createdByUser": {
                "id": "",
                "username": "",
                "first": "",
                "last": "",
                "role": 0
            },
            "createdAt": 1505937447295,
            "lastUpdatedByUser": {
                "id": "5197072786522112",
                "username": "[email protected]",
                "first": "Adam",
                "last": "Lohner",
                "role": 8
            },
            "lastUpdatedAt": 1505938327653
        },
        "dirty": false,
        "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
        "elementPathRules": [
            "a:contains('Data Presentation')"
        ]
    },
    { feature #2 ... },
    { feature #3 ... }
]
Attributes
createdByUser
user
The user that created the feature.
createdAt
timestamp
The timestamp in milliseconds after the epoch when the feature was created.
lastUpdatedByUser
user
The user that last updated the feature.
lastUpdatedAt
timestamp
The timestamp in milliseconds after the epoch when the feature was last updated.
kind
string
Returns the type of object. Feature for example.
rootVersionId
string
The unique identifier of the root entity, which nominally matches the public id field of the feature.
stableVersionId
string
The unique identifier for the current version of the feature.
id
string
The unique identifier for the feature.
name
string
Display name for the feature.
color
string
Color value associated with the Feature. For visualization in Paths and Funnels.
group
array[object]
Object containing information related to associated group for the feature.
dirty
boolean
Boolean value returned if feature is processing at the time of request.
elementPathRules
array[object]
The element path that indicates where the feature can be found (blank if not applicable).

Return list of all features

Definition

GET https://app.pendo.io/api/v1/feature
requests.get('https://app.pendo.io/api/v1/feature')

Example request

curl -X GET \
  https://app.pendo.io/api/v1/feature \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
headers = {
    'content-type': 'application/json',
    'x-pendo-integration-key': '63bd1cda-db5a-4a2b-633b-37b8b0c5462c',
}
requests.get('https://app.pendo.io/api/v1/feature', headers = headers)

Example response

[{
        "createdByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "createdAt": 1505938327432,
        "lastUpdatedByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "lastUpdatedAt": 1505938327432,
        "kind": "Feature",
        "rootVersionId": "UB9RTn0B9esKqPW_NcfB25n3QAc",
        "stableVersionId": "UB9RTn0B9esKqPW_NcfB25n3QAc-20170920201207.432160413",
        "id": "UB9RTn0B9esKqPW_NcfB25n3QAc",
        "name": "Data Presentation Toggle Dropdown",
        "color": "gray",
        "group": {
            "id": "_PENDO_DEFAULTGROUP_01_",
            "name": "Dashboard",
            "description": "",
            "color": ".groupColor01",
            "length": 6,
            "items": [],
            "createdByUser": {
                "id": "",
                "username": "",
                "first": "",
                "last": "",
                "role": 0
            },
            "createdAt": 1505937447295,
            "lastUpdatedByUser": {
                "id": "5197072786522112",
                "username": "[email protected]",
                "first": "Adam",
                "last": "Lohner",
                "role": 8
            },
            "lastUpdatedAt": 1505938327653
        },
        "dirty": false,
        "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
        "elementPathRules": [
            "a:contains('Data Presentation')"
        ]
    },
    { feature #2 ... },
    { feature #3 ... }
]

Returns full list of features

Details
Method GET
URI /api/v1/feature
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Return a specific feature

Definition

GET https://app.pendo.io/api/v1/feature?id={featureId}
requests.get("https://app.pendo.io/api/v1/feature", params = "{featureId}")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/feature?id=UB9RTn0B9esKqPW_NcfB25n3QAc \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/feature"
params = {
    "id": "UB9RTn0B9esKqPW_NcfB25n3QAc"
}
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers, params = params)

Example response

[{
    "createdByUser": {
        "id": "5197072786522112",
        "username": "[email protected]",
        "first": "Adam",
        "last": "Lohner",
        "role": 8
    },
    "createdAt": 1505938327432,
    "lastUpdatedByUser": {
        "id": "5197072786522112",
        "username": "[email protected]",
        "first": "Adam",
        "last": "Lohner",
        "role": 8
    },
    "lastUpdatedAt": 1505938327432,
    "kind": "Feature",
    "rootVersionId": "UB9RTn0B9esKqPW_NcfB25n3QAc",
    "stableVersionId": "UB9RTn0B9esKqPW_NcfB25n3QAc-20170920201207.432160413",
    "id": "UB9RTn0B9esKqPW_NcfB25n3QAc",
    "name": "Data Presentation Toggle Dropdown",
    "color": "gray",
    "group": {
        "id": "_PENDO_DEFAULTGROUP_01_",
        "name": "Dashboard",
        "description": "",
        "color": ".groupColor01",
        "length": 6,
        "items": [],
        "createdByUser": {
            "id": "",
            "username": "",
            "first": "",
            "last": "",
            "role": 0
        },
        "createdAt": 1505937447295,
        "lastUpdatedByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "lastUpdatedAt": 1505938327653
    },
    "dirty": false,
    "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
    "elementPathRules": [
        "a:contains('Data Presentation')"
    ]
}]

Instead of returning all features, you can specify a singular feature you’d like returned by adding a {featureId} to the request.

Details
Method GET
URI /api/v1/feature?id={featureId}
Parameters {featureId} - id of the feature to return
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Return list of specific features

Definition

GET https://app.pendo.io/api/v1/feature?id={featureId_1},{featureId_2},{featureId_3}
requests.get("https://app.pendo.io/api/v1/feature", params = "{featureId}")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/feature?id=UB9RTn0B9esKqPW_NcfB25n3QAc,x29i5gWvIXAVoCt3ShlUYx5lgpQ \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/feature"
params = {
    "id": "UB9RTn0B9esKqPW_NcfB25n3QAc,x29i5gWvIXAVoCt3ShlUYx5lgpQ"
}
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers, params = params)

Example response

 [
  { featureId_1 details },
  { featureId_2 details },
  { ... }
]

Returns JSON array of comma separated featureIds specified in the request.

Details
Method GET
URI /api/v1/feature?id={featureId_1},{featureId_2},{featureId_3}
Parameters {featureId} - id(s) of the feature to return
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Guide

Guide endpoint

https://app.pendo.io/api/v1/guide

The {guideid} referenced below can be found at the end of the URL when viewing an individual guide details page. You can access that page by going to the guides list and then clicking into any guide.

The guide object

Example response

[{
    "createdByUser": {
        "id": "5197072786522112",
        "username": "[email protected]",
        "first": "Adam",
        "last": "Lohner",
        "role": 8
    },
    "createdAt": 1506358424254,
    "lastUpdatedByUser": {
        "id": "5197072786522112",
        "username": "[email protected]",
        "first": "Adam",
        "last": "Lohner",
        "role": 8
    },
    "lastUpdatedAt": 1506358852110,
    "kind": "Guide",
    "rootVersionId": "T6v10_CxHlvAkROQODuKYD2nzJ8",
    "stableVersionId": "T6v10_CxHlvAkROQODuKYD2nzJ8-20170925170052.110513720",
    "id": "T6v10_CxHlvAkROQODuKYD2nzJ8",
    "name": "API Documentation Guide",
    "state": "staged",
    "launchMethod": "auto",
    "isMultiStep": false,
    "steps": [{ step object }],
    "attributes": { ... },
    "audience": [{
            "source": {
                "visitors": null
            }
        },
        {
            "select": {
                "visitorId": "visitorId"
            }
        },
        {
            "identified": "visitorId"
        }
    ],
    "audienceUiHint": {
        "filters": []
    },
    "resetAt": 0,
    "publishedAt": 0
}]
Attributes
createdByUser
user
The user that created the guide.
createdAt
timestamp
The timestamp in milliseconds after the epoch when the guide was created.
lastUpdatedByUser
user
The user that last updated the guide.
lastUpdatedAt
timestamp
The timestamp in milliseconds after the epoch when the guide was last updated.
kind
string
Returns the type of object. Guide for example.
rootVersionId
string
The unique identifier of the root entity, which nominally matches the public id field of the guide.
stableVersionId
string
The unique identifier for the current version of the guide.
id
string
The unique identifier for the guide.
name
string
Display name for the guide.
state
string
The current state of the guide. published, staged, draft, and disabled.
launchMethod
string
Also referred to as the “activation” method. api, automatic, badge, dom, and launcher.
isMultiStep
boolean
Returnstrue if guide has multiple steps (walkthrough).
steps
array[GuideStep]
Array of objects, one for each step of a multi-step walkthrough guide.
attributes
array[attributes]
Data used for the agent’s handling of the guide.
audience
array[Pipeline]
Object representing the targeted segment rules.
audienceUiHint
array[Filter]
Internal values to build audience rules.
resetAt
timestamp
The timestamp in milliseconds when the guide’s data was last reset.
publishedAt
timestamp
The timestamp in milliseconds when the guide state was last set to public.

The step object

Example response

[{
    "id": "TGgwmKNkUBKIyHbrpbNmpEzS7mU",
    "guideId": "T6v10_CxHlvAkROQODuKYD2nzJ8",
    "type": "lightbox",
    "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
    "regexUrlRule": "^https?://[^/]*/?(?:;[^#]*)?(?:\\?[^#]*)?(?:#.*)?$",
    "elementPathRule": "",
    "contentType": "text/html; charset=utf-8",
    "contentUrl": "https://pendo-static-5335432811773952.storage.googleapis.com/guide-content/T6v10_CxHlvAkROQODuKYD2nzJ8/TGgwmKNkUBKIyHbrpbNmpEzS7mU/ORZOI2Ynpl0qDCiohWyhj48flZQ",
    "contentUrlCss": "https://pendo-static-5335432811773952.storage.googleapis.com/guide-content/T6v10_CxHlvAkROQODuKYD2nzJ8/TGgwmKNkUBKIyHbrpbNmpEzS7mU/Z9yGnCH1bZIPNqYOk8x_KPB-FI4.guide.css",
    "contentUrlJs": "https://pendo-static-5335432811773952.storage.googleapis.com/guide-content/T6v10_CxHlvAkROQODuKYD2nzJ8/TGgwmKNkUBKIyHbrpbNmpEzS7mU/vzsZ7wh2C-uB56euYUiYPJKtK80.guide.js",
    "rank": 5000000,
    "advanceMethod": "button",
    "attributes": {
        "height": 500,
        "width": 500,
        "autoHeight": true,
        "css": "/* --- Selectors from Global CSS --- */\n._pendo-guide-container_ {\n    /* Guide border, shadow, background, etc. */\n    background-color: white;\n    padding: 40px;\n    color: #333;\n    line-height: 140%;\n}\n._pendo-guide-container_ ._pendo-guide-content_ {\n    /* Content area: use for font attributes, padding, etc. */\n    text-align: left;\n    padding: 0\n}\n._pendo-guide-container_ ._pendo-close-guide_ {\n    /* Close guide icon */\n    display: inline;\n    font-size: 32px;\n    font-weight: 100;\n    top: 6px;\n    right: 15px;\n    color: #ccc;\n}\n._pendo-guide-container_ ._pendo-close-guide_:hover {\n    /* Close guide icon hover effects*/\n    color: #999;\n}.guide-header-text { font-weight: bold; font-size: 36px;}"
    },
    "lastUpdatedAt": 1506358426018,
    "resetAt": 0
}]
Attributes
id
string
Unique identifier for the step.
guideId
string
ID of the parent guide.
type
string
The type of guide step (Lightbox, Banner, Tooltip, etc.)
elementPathRule
string
The element path that indicates where the tooltip or badge “points” to (blank if not applicable).
contentType
string
The MIME type text/html or application/javascript of the content of this guide step.
contentUrl
string
URL for the step html content.
contentUrlCss
string
URL for the step css content.
contentUrlJs
string
URL for the step JS content.
rank
number
The rank order of this guide step among the other guide steps.
advanceMethod
string
Returns the steps advance method - button, programatic, or element.
thumbnailUrls
string
Thumbnail URLS used for the screenshots.
attributes
array[string]
Data used for the agent’s handling of the guide step. Contains step properties such as the height, width, autoHeight, position, css, and variables.
lastUpdatedAt
timestamp
The timestamp in milliseconds when the guide step was last updated.
resetAt
timestamp
The timestamp in milliseconds when the guide data was last reset.

The attributes object

Example response

{
    "type": "lightbox",
    "device": {
        "type": "desktop"
    },
    "badge": {
        "position": "top-right",
        "color": "#6a6c75",
        "name": "empty-i",
        "offsets": {
            "top": 0,
            "right": 0,
            "left": 0
        },
        "showOnEvent": "always",
        "useHover": "no",
        "isOnlyShowOnce": false,
        "canChangeBadgeColor": true,
        "imageUrl": "https://pendo-static-5335432811773952.storage.googleapis.com/empty-i_6a6c75",
        "width": 13,
        "height": 13
    },
    "priority": 0,
    "launcher": {
        "keywords": []
    }
}
Attributes
type
string
Unique identifier for the step.
device
boolean or string
The current state of the guide.
desktop (boolean)
mobile (boolean)
type: desktop (string)
badge
array
Attributes related to the badge activation type.
priority
number
Position of the Guide as it appears in the launcher/guide center.
launcher
array[string]
Returns an array of keywords used to search from within the launcher/guide center.

Return list of all guides

Definition

GET https://app.pendo.io/api/v1/guide
requests.get("https://app.pendo.io/api/v1/guide")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/guide \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/guide"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

Example response

[{
        "createdByUser": { ... },
        "createdAt": 1506358424254,
        "lastUpdatedByUser": { ... },
        "lastUpdatedAt": 1506358852110,
        "kind": "Guide",
        "rootVersionId": "T6v10_CxHlvAkROQODuKYD2nzJ8",
        "stableVersionId": "T6v10_CxHlvAkROQODuKYD2nzJ8-20170925170052.110513720",
        "id": "T6v10_CxHlvAkROQODuKYD2nzJ8",
        "name": "API Documentation Guide",
        "state": "staged",
        "launchMethod": "auto",
        "isMultiStep": false,
        "steps": [{
            "id": "TGgwmKNkUBKIyHbrpbNmpEzS7mU",
            "guideId": "T6v10_CxHlvAkROQODuKYD2nzJ8",
            "type": "lightbox",
            "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
            "regexUrlRule": "^https?://[^/]*/?(?:;[^#]*)?(?:\\?[^#]*)?(?:#.*)?$",
            "elementPathRule": "",
            "contentType": "text/html; charset=utf-8",
            "contentUrl": "https://pendo-static-5335432811773952.storage.googleapis.com/guide-content/T6v10_CxHlvAkROQODuKYD2nzJ8/TGgwmKNkUBKIyHbrpbNmpEzS7mU/ORZOI2Ynpl0qDCiohWyhj48flZQ",
            "contentUrlCss": "https://pendo-static-5335432811773952.storage.googleapis.com/guide-content/T6v10_CxHlvAkROQODuKYD2nzJ8/TGgwmKNkUBKIyHbrpbNmpEzS7mU/Z9yGnCH1bZIPNqYOk8x_KPB-FI4.guide.css",
            "contentUrlJs": "https://pendo-static-5335432811773952.storage.googleapis.com/guide-content/T6v10_CxHlvAkROQODuKYD2nzJ8/TGgwmKNkUBKIyHbrpbNmpEzS7mU/vzsZ7wh2C-uB56euYUiYPJKtK80.guide.js",
            "rank": 5000000,
            "advanceMethod": "button",
            "attributes": {
                "height": 500,
                "width": 500,
                "autoHeight": true,
                "css": "/* --- Selectors from Global CSS --- */\n._pendo-guide-container_ {\n    /* Guide border, shadow, background, etc. */\n    background-color: white;\n    padding: 40px;\n    color: #333;\n    line-height: 140%;\n}\n._pendo-guide-container_ ._pendo-guide-content_ {\n    /* Content area: use for font attributes, padding, etc. */\n    text-align: left;\n    padding: 0\n}\n._pendo-guide-container_ ._pendo-close-guide_ {\n    /* Close guide icon */\n    display: inline;\n    font-size: 32px;\n    font-weight: 100;\n    top: 6px;\n    right: 15px;\n    color: #ccc;\n}\n._pendo-guide-container_ ._pendo-close-guide_:hover {\n    /* Close guide icon hover effects*/\n    color: #999;\n}.guide-header-text { font-weight: bold; font-size: 36px;}"
            },
            "lastUpdatedAt": 1506358426018,
            "resetAt": 0
        }],
        "attributes": {
            "type": "lightbox",
            "device": {
                "type": "desktop"
            },
            "badge": {
                "position": "top-right",
                "color": "#6a6c75",
                "name": "empty-i",
                "offsets": {
                    "top": 0,
                    "right": 0,
                    "left": 0
                },
                "showOnEvent": "always",
                "useHover": "no",
                "isOnlyShowOnce": false,
                "canChangeBadgeColor": true,
                "imageUrl": "https://pendo-static-5335432811773952.storage.googleapis.com/empty-i_6a6c75",
                "width": 13,
                "height": 13
            },
            "priority": 0,
            "launcher": {
                "keywords": []
            }
        },
        "audience": [{
                "source": {
                    "visitors": null
                }
            },
            {
                "select": {
                    "visitorId": "visitorId"
                }
            },
            {
                "identified": "visitorId"
            }
        ],
        "audienceUiHint": {
            "filters": []
        },
        "resetAt": 0,
        "publishedAt": 0
    },
    { guide #2 },
    { guide #3 }
]

Returns a JSON list of all guides for a subscription.

Details
Method GET
URI /api/v1/guide
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Return a specific guide

Definition

GET https://app.pendo.io/api/v1/guide?id={guideid}
requests.get("https://app.pendo.io/api/v1/guide", params = "{guideid}")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/guide?id=T6v10_CxHlvAkROQODuKYD2nzJ8 \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
url = "https://app.pendo.io/api/v1/guide"
params = {
    "id": "T6v10_CxHlvAkROQODuKYD2nzJ8"
}
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers, params = params)

Example response

[{
    "createdByUser": {},
    "createdAt": 1506358424254,
    "lastUpdatedByUser": {},
    "lastUpdatedAt": 1506358852110,
    "kind": "Guide",
    "rootVersionId": "T6v10_CxHlvAkROQODuKYD2nzJ8",
    "stableVersionId": "T6v10_CxHlvAkROQODuKYD2nzJ8-20170925170052.110513720",
    "id": "T6v10_CxHlvAkROQODuKYD2nzJ8",
    "name": "API Documentation Guide",
    "state": "staged",
    "launchMethod": "auto",
    "isMultiStep": false,
    "steps": [{ ... }],
    "attributes": { ... },
    "audience": [{ ... }],
    "audienceUiHint": {
        "filters": []
    },
    "resetAt": 0,
    "publishedAt": 0
}]

Instead of returning all guides, you can specify a singular guide you’d like returned by adding a {guideid} to the request. Comma separated values are allowed. For example, if you wanted to return multiple guides but not the entire list, follow the format: guide?id={guideid_1},{guideid_2},{guideid_3}

Details
Method GET
URI /api/v1/guide?={guideid}
Parameters guideId - the ID of the guide requested
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Retrieve change history for a guide

Definition

GET https://app.pendo.io/api/v1/guide/{guideId}/history
requests.get("https://app.pendo.io/api/v1/guide/{guideid}/history")

Example request

curl -X GET \
https://app.pendo.io/api/v1/guide/T6v10_CxHlvAkROQODuKYD2nzJ8/history \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/guide/T6v10_CxHlvAkROQODuKYD2nzJ8/history"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

Example response

[{
        "createdByUser": { ... },
        "createdAt": 1506358424254,
        "lastUpdatedByUser": { ... },
        "lastUpdatedAt": 1506358426018,
        "kind": "Guide",
        "rootVersionId": "T6v10_CxHlvAkROQODuKYD2nzJ8",
        "stableVersionId": "T6v10_CxHlvAkROQODuKYD2nzJ8-20170925165346.018238252",
        "id": "T6v10_CxHlvAkROQODuKYD2nzJ8",
        "name": "API Documentation Guide",
        "state": "draft",
        "launchMethod": "auto",
        "isMultiStep": false,
        "steps": [{ ... }],
        "attributes": { ... },
        "audience": [{ ... }],
        "audienceUiHint": {
            "filters": []
        },
        "resetAt": 0,
        "publishedAt": 0
    },
    { next oldest version (if applicable) },
  { ... }
]

Returns a JSON list of all versions of a guide, from current to oldest. Changes to guides through the Pendo user interface often result in multiple individual updates, each of which will be independently reflected in the history.

Details
Method GET
URI /api/v1/guide/{guideid}/history
Parameters guideid - the ID of the guide whose history is needed
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: guide was located and history found.
404: guide in question was not found.

Reset guide seen for specific visitor

Definition

POST https://app.pendo.io/api/v1/guide/{guideid}/visitor/{visitorId}/reset
requests.post("https://app.pendo.io/api/v1/guide/{guideid}/visitor/{visitorId}/reset")

Example request

curl -X POST \
 https://app.pendo.io/api/v1/guide/T6v10_CxHlvAkROQODuKYD2nzJ8/visitor/4/reset \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d ''
import requests
url = "https://app.pendo.io/api/v1/guide/T6v10_CxHlvAkROQODuKYD2nzJ8/visitor/4/reset"
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/json"
}
response = requests.post(url, headers = headers)

Reset the guide seen records for a guide with ID {guideid} for a particular visitor with ID {visitorId}. The guide can be in any state.

Details
Method POST
URI /api/v1/guide/{guideid}/visitor/{visitorid}/reset
Parameters guideid - ID of the guide to be reset
visitorId - ID of the visitor whose record of having seen the guide should be removed.
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: guide was reset as requested.
404: The guide in question was not found.

Reset guide seen for specific visitor for all guides

Definition

POST https://app.pendo.io/api/v1/guide/all/visitor/{visitorId}/reset
requests.post("https://app.pendo.io/api/v1/guide/all/visitor/{visitorId}/reset")

Example request

curl -X POST \
https://app.pendo.io/api/v1/guide/all/visitor/4/reset \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d ''
import requests
url = "https://app.pendo.io/api/v1/guide/all/visitor/4/reset"
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/json"
}
response = requests.post(url, headers = headers)

Reset the guide seen records for a particular visitor with ID {visitorId}. All seen data will be removed across all guides for that visitor.

Details
Method POST
URI /api/v1/guide/all/visitor/{visitorId}/reset
Parameters visitorId - ID of the visitor whose record of having seen all guides should be removed.
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: guide was reset as requested.

Reset individual staged guide

Definition

POST https://app.pendo.io/api/v1/guide/{guideid}/reset
requests.post("https://app.pendo.io/api/v1/guide/{guideid}/reset")

Example request

curl -X POST \
https://app.pendo.io/api/v1/guide/T6v10_CxHlvAkROQODuKYD2nzJ8/reset \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d ''
import requests
url = "https://app.pendo.io/api/v1/guide/T6v10_CxHlvAkROQODuKYD2nzJ8/reset"
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/json"
}
response = requests.post(url, headers = headers)

Reset an individual staged guide with ID guideid. All visitors that have seen the guide previously will be eligible to see it again as if it were a newly created guide. All previous guide data will be deleted for this guide, including any poll response data.

Details
Method POST
URI /api/v1/guide/{guideid}/reset
Parameters guideid - ID of the guide to be reset.
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: guide was reset as requested.
400: The guide could not be reset (e.g. it’s not a staged guide).
404: The guide in question was not found.

Reset all staged guides

Definition

POST https://app.pendo.io/api/v1/guide/staged/reset
requests.post("https://app.pendo.io/api/v1/guide/staged/reset")

Example request

curl -X POST \
 https://app.pendo.io/api/v1/guide/staged/reset \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d ''
import requests
url = "https://app.pendo.io/api/v1/guide/staged/reset"
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/json"
}
response = requests.post(url, headers = headers)

Reset all staged guides. All visitors that have seen guides previously will be eligible to them again as if they were newly created guides. All previous guide data will be deleted, including any poll response data.

Details
Method POST
URI /api/v1/guide/staged/reset
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: All guides were reset as requested.

Bulk Export XLIFF

Definition

GET https://app.pendo.io/api/v1/guide/localization/export?guideids=x,y,...
requests.get("https://app.pendo.io/api/v1/guide/localization/export?guideids=x,y,...")

Example request

curl -X GET \
 https://app.pendo.io/api/v1/guide/localization/export?guideids=x,y,... \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d ''
import requests
url = "https://app.pendo.io/api/v1/guide/localization/export?guideids=x,y,..."
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
}
response = requests.get(url, headers = headers)

Example response

<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file original="Guide1" datatype="" source-language="en-US" target-language="">
        ....
    </file>
    <file original="Guide2" datatype="" source-language="en-US" target-language="">
        ....
    </file>
</xliff>

Export XLIFF XML for up to 15 guides per request. Guides are selected by guideid. Response contains XML with each guide XLIFF contained in a file tag. The Resource Center and P1 guides are not supported. Any incorrect guideids will cause the request to fail. The subscription must have localization enabled in Settings.

Details
Method GET
URI /api/v1/guide/localization/export?guideids=x,y,...
Request Headers x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Success
400: Bad Request. More than 15 guides requested.
400: Bad Request. Guide ids must be provided.
400: Bad Request. guideid is resourcecenter.
400: Bad Request. Guide id : P1 guides are not supported.
400: Bad Request. Localization is not enabled for guide’s application.
404: Not Found. guide id not found.
500: Server Error. Any other failure.

Bulk Import XLIFF

Definition

POST https://app.pendo.io/api/v1/guide/localization/import
requests.post("https://app.pendo.io/api/v1/guide/localization/import")

Example request

curl -X POST \
 https://app.pendo.io/api/v1/guide/localization/import \
  -H 'content-type: application/xml; charset=UTF-8' \
    -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d ''
import requests
url = "https://app.pendo.io/api/v1/guide/localization/import"
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/xml; charset=UTF-8"
}
response = requests.post(url, headers = headers)
{
  guide_Id : {
  lang_code: string/translation state,
  lang_code: string/translation state,
  ...}
  guide_Id : {
  lang_code: string/translation state,
  ...}
  guide_Id : {
  lang_code: string/translation state,
  ...}
}

Import up to 15 XLIFF 1.2 files per request. Each file is one guideid/target language combination. Import validates each file and will continue to the next file if an import fails. XLIFF files must be formatted correctly. Only P2 guides are supported. The subscription must have localization and target language enabled in Settings. Integration key requires Read/Write access.

Details
Method POST
URI /api/v1/guide/localization/import
Request Headers content-type: application/xml; charset=UTF-8
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Success
400: Bad Request. Exceeds limit of 15 translations.
400: Bad Request. XLIFF Version string must be \"1.2\".
400: Bad Request. Improperly formatted XLIFF request.
400: Bad Request. XLIFF File has guideid and target language duplicates.
207: Multi-Status. : Localization is not enabled for this guide’s application.
207: Multi-Status. : guide id not found.
207: Multi-Status. : Target language is not enabled for the app.
207: Multi-Status. : P1 guides are not supported.
207: Multi-Status. : Resourcecenter is not supported.

Metadata

The metadata object

Example response

{
    "agent": { ... },
    "auto": { ... },
    "custom": { ... },
    "pendo": {
      "blacklistguides": true
    }
}
Attributes
agent
array
Metadata type passed through the installation snippet.
auto
string
Automatically generated by Pendo.
custom
array
Custom “Pendo only” fields to help analyze aspects of your data.
pendo
string
Metadata representing the current blacklistguides setting for the visitor.

Automatically generated metadata

Example visitor "auto" object

{
    "accountid": "Epsilon united",
    "accountids": [
        "Epsilon united"
    ],
    "firstvisit": 1506351511034,
    "id": "4",
    "idhash": 4088798008,
    "lastbrowsername": "Chrome",
    "lastbrowserversion": "60.0.3112",
    "lastoperatingsystem": "Mac OS X",
    "lastservername": "pendosandbox.com",
    "lastupdated": 1506358391050,
    "lastuseragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
    "lastvisit": 1506358390891,
    "nid": 4
}
Visitor Attributes
accountid
string
Unique identifier for the account the visitor belongs to.
accountids
array
Array of unique accountIds the visitor belongs to.
firstvisit
timestamp
The timestamp in milliseconds after the epoch when an event was first captured for the visitor.
id
string
Unique identifier for the visitor.
idhash
number
Hash of visitor Id.
lastbrowsername
string
Most recent browser name.
lastbrowserversion
string
Most recent browser version.
lastoperatingsystem
string
Most recent operating system.
lastservername
string
Most recent server name.
lastupdated
timestamp
The timestamp in milliseconds after the epoch when the visitor was last updated.
lastuseragent
string
Most recent user agent (unparsed).
lastvisit
timestamp
The timestamp in milliseconds after the epoch when we last recorded an event for the visitor.
nid
number
Numeric id for the visitor.

Example account "auto" object

{
    "firstvisit": 1506349414089,
    "id": "Zeta and Sons",
    "idhash": 1129480058,
    "lastupdated": 1506349414757,
    "lastvisit": 1506349414089
}
Account Attributes
firstvisit
timestamp
The timestamp in milliseconds after the epoch when the account or visitor was created.
id
string
Unique identifier for the visitor or account.
idhash
number
Hash of account Id.
lastupdated
timestamp
The timestamp in milliseconds after the epoch when the account was last updated.
lastvisit
timestamp
The timestamp in milliseconds after the epoch when we last recorded an event for the account.

Get a metadata schema

Definition

GET https://app.pendo.io/api/v1/metadata/schema/{kind}
requests.get("https://app.pendo.io/api/v1/metadata/schema/{kind}")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/metadata/schema/account \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/metadata/schema/account"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

Example response

{
    "auto": {
        "firstvisit": {
            "Type": "time",
            "DisplayName": "First Visit",
            "ElementType": "",
            "ElementFormat": "milliseconds",
            "Dirty": false,
            "isHidden": false,
            "isDeleted": false,
            "isCalculated": false,
            "neverIndex": false
        },
        "id": {
            "Type": "string",
            "DisplayName": "Account ID",
            "ElementType": "",
            "ElementFormat": "",
            "Dirty": false,
            "isHidden": false,
            "isDeleted": false,
            "isCalculated": false,
            "neverIndex": false
        },
        "lastvisit": {
            "Type": "time",
            "DisplayName": "Last Visit",
            "ElementType": "",
            "ElementFormat": "milliseconds",
            "Dirty": false,
            "isHidden": false,
            "isDeleted": false,
            "isCalculated": false,
            "neverIndex": false
        }
    }
}

Gets the metadata schema for a single kind of metadata (visitor or account).

Details
Method GET
URI /api/v1/metadata/schema/{kind}
Parameters kind - "visitor" or "account".
Data JSON encoded metadata value
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: The metadata value was updated
404: Check to make sure the custom field exists in Data Mappings and that the visitor or account ID is valid

Get value of a metadata field

Definition

GET https://app.pendo.io/api/v1/metadata/{kind}/{group}/value/{id}/{fieldName}
requests.get("https://app.pendo.io/api/v1/metadata/{kind}/{group}/value/{id}/{fieldName}")

Example request

curl -X GET \
https://app.pendo.io/api/v1/metadata/visitor/agent/value/4/email \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/metadata/visitor/agent/value/4/email"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

Example response

"[email protected]"

Gets the value of metadata field for an account or visitor

Details
Method GET
URI /api/v1/metadata/{kind}/{group}/value/{id}/{fieldName}
Parameters kind - "visitor" or "account"
id - ID of the visitor or account being updated
fieldName - name of the metadata field being updated
Data JSON encoded metadata value
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: The metadata value was updated
404: Check to make sure the custom field exists in Data Mappings and that the visitor or account ID is valid

Opt-out a visitor or account from all guides

Definition

PUT https://app.pendo.io/api/v1/metadata/{kind}/pendo/value/{id}/blacklistguides
requests.put("https://app.pendo.io/api/v1/metadata/{kind}/pendo/value/{id}/blacklistguides", data = "{boolean}")

Example request

curl -X PUT \
  https://app.pendo.io/api/v1/metadata/visitor/pendo/value/4/blacklistguides \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d true
import requests
url = "https://app.pendo.io/api/v1/metadata/visitor/pendo/value/4/blacklistguides"
data = "true"
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/json"
}
response = requests.put(url, data = data, headers = headers)

Use ‘Pendo’ metadata to turn guides off or on for a visitor or an account. This provides an opt-out capability for visitors and accounts. To use this capability, turn on the ‘Enable guide blacklist per visitor and account’ subscription setting. Without this setting, attempts to set blacklistguides metadata will fail.

Details
Method PUT
URI /api/v1/metadata/{kind}/pendo/value/{id}/blacklistguides
Parameters kind - "visitor" or "account"
id - ID of the visitor or account being updated
Data true to disable guides
false to re-enable guides
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: The metadata value was updated

Opt-out or Do Not Process a Visitor in Pendo

Definition

PUT https://app.pendo.io/api/v1/metadata/visitor/pendo/value/{id}/donotprocess
requests.put("https://app.pendo.io/api/v1/metadata/visitor/pendo/value/{id}/donotprocess", data = "{boolean}")

Example request

curl -X PUT \
  https://app.pendo.io/api/v1/metadata/visitor/pendo/value/4/donotprocess \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d true
import requests
url = "https://app.pendo.io/api/v1/metadata/visitor/pendo/value/4/donotprocess"
data = "true"
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/json"
}
response = requests.put(url, data = data, headers = headers)

Use this flag to opt-out a visitors from all Pendo analytics and Guides. This flag is typically used to help companies align to GDPR requirements where a user can invoke their data right(s). Learn more about GDPR at Pendo.

How does Pendo use this flag?

If you select "do not process" for a visitor, the agent will recognize that it’s a "do not process" visitor on the first hit of a visitor and immediately discard the data. For subsequent visits, Pendo already knows the visitor is DNP and does not even collect any data. For agent versions lower than 2.15.6, Pendo will immediately discard the data.

Note: Data for "Do Not Process" Visitors are non-recoverable, regardless of agent version.

Details
Method PUT
URI /api/v1/metadata/{kind}/pendo/value/{id}/donotprocess
Parameters id - ID of the visitor being updated
Data true to opt-out visitor from being processed in Pendo
false to process visitor in Pendo
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: The metadata value was updated

Set value for an agent or custom field

Definition

PUT https://app.pendo.io/api/v1/metadata/{kind}/{group}/value/{id}/{fieldName}
requests.put("https://app.pendo.io/api/v1/metadata/{kind}/{group}/value/{id}/{fieldName}", data = "{value}")

Example request

curl -X PUT \
  https://app.pendo.io/api/v1/metadata/visitor/custom/value/4/location \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d '"Alaska"'
import requests
url = "https://app.pendo.io/api/v1/metadata/visitor/custom/value/4/location"
data = "\"Alaska\""
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/json"
}
response = requests.put(url, data = data, headers = headers)

Sets the value of an agent or custom metadata field on an account or visitor. If setting value for a custom field, the field must already have been created in the Data Mappings.

Details
Method PUT
URI /api/v1/metadata/{kind}/{group}/value/{id}/{fieldName}
Parameters kind - "visitor" or "account"
group - type of metadata field: agent or custom
id - id of the visitor or account being updated
fieldName - name of the metadata field being updated
Data JSON encoded metadata value
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: The metadata value was updated
404: Check to make sure the custom field exists in Data Mappings

Set value for a set of agent or custom fields

Definition

POST https://app.pendo.io/api/v1/metadata/{kind}/{group}/value
requests.post("https://app.pendo.io/api/v1/metadata/{kind}/{group}/value", data = "JSON array")

The contents of the POST must be a JSON array:

[ object1, object2, ..., objectN ]

Each object in the array is of the form:

{
  "visitorId": "4",
  "values": {
    "firstname": "Quam",
    "lastname": "Quis"
  }
}

Example request

curl -X POST \
https://app.pendo.io/api/v1/metadata/visitor/agent/value \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: <PENDO_INTEGRATION_KEY>' \
  -d '[{"visitorId":"4","values":{"firstname":"Quam","lastname":"Quis"}},{"visitorId":"45","values":{"firstname":"Vel","lastname":"Quam"}},{"visitorId":"63","values":{"firstname":"Eros","lastname":"Nam"}}]'
import requests
url = "https://app.pendo.io/api/v1/metadata/visitor/agent/value"
data = "[{\"visitorId\":\"4\",\"values\":{\"firstname\":\"Quam\",\"lastname\":\"Quis\"}},{\"visitorId\":\"45\",\"values\":{\"firstname\":\"Vel\",\"lastname\":\"Quam\"}},{\"visitorId\":\"63\",\"values\":{\"firstname\":\"Eros\",\"lastname\":\"Nam\"}}]"
headers = {
    'x-pendo-integration-key': "<PENDO_INTEGRATION_KEY>",
    'content-type': "application/json",
}
response = requests.post(url, data = data, headers = headers)

Sets the value of multiple metadata fields on set of accounts or visitors. If setting custom fields, the fields must already have been created in the Data Mappings.

Any number of records may be submitted for update, but the call is limited to five (5) minutes. Any calls that takes longer will timeout with a 408 Request Timeout.

Details
Method POST
URI /api/v1/metadata/{kind}/{group}/value
Parameters kind - "visitor" or "account"
group - type of metadata field: agent or custom
Data JSON array (see example format)
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: The bulk update completed.
400: The format is unacceptable due to malformed JSON or missing field mappings.
408: The call took too long and timed out.
Response

Example response

{
    "total": 3,
    "updated": 3,
    "failed": 0,
    "missing": [],
    "errors": []
}
Attributes
total
number
Sum of updated + failed.
failed
number
Sum of length(missing) + length(errors).

Accepted Date Formats

When attempting to update Date fields, please be sure to only use accepted formats. Sending unaccepted date format data into a date field can have unexpected consequences for any data entries or edits.

  • 1136232245 (s)
  • 1136232245426 (ms)
  • Mon Jan 02 2006
  • Mon Jan 02 2006 15:04:05 MST-0700
  • 01/02/2006 03:04pm
  • ISO8601 W3C, ex: 2006-01-02T115:04:05.999-05:00
  • 2006-01-02T15:04:05-0700
  • 2006-01-02T15:04:05-07:00
  • 2006-01-02T15:04:05.999-07:00
  • 2006-01-02T15:04:05Z07:00
  • 2006-01-02T15:04:05.99Z
  • 2006-01-02T15:04:05
  • 2006-01-02 15:04:05 -0700
  • 2006-01-02 15:04:05 MST
  • 2006-01-02 15:04:05

Page

Page Endpoint

https://app.pendo.io/api/v1/page

The {pageId} referenced below can be found at the end of the URL when viewing details for a specific page within the app. You can view your list of available pages here.

The page object

Example response

[{
    "createdByUser": {
        "id": "5197072786522112",
        "username": "[email protected]",
        "first": "Adam",
        "last": "Lohner",
        "role": 8
    },
    "createdAt": 1505938241596,
    "lastUpdatedByUser": {
        "id": "5197072786522112",
        "username": "[email protected]",
        "first": "Adam",
        "last": "Lohner",
        "role": 8
    },
    "lastUpdatedAt": 1505938241596,
    "kind": "Page",
    "rootVersionId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
    "stableVersionId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM-20170920201041.596687476",
    "id": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
    "name": "Dashboard",
    "color": "gray",
    "group": { ... },
    "dirty": false,
    "rules": [{
        "rule": "//*",
        "designerHint": "http://pendosandbox.com/",
        "parsedRule": "^https?://[^/]*/?(?:;[^#]*)?(?:\\?[^#]*)?(?:#.*)?$"
    }]
}]
Attributes
createdByUser
user
The user that created the page.
createdAt
timestamp
The timestamp in milliseconds after the epoch when the page was created.
lastUpdatedByUser
user
The user that last updated the page.
lastUpdatedAt
timestamp
The timestamp in milliseconds after the epoch when the page was last updated.
kind
string
Returns the type of object. Page for example.
rootVersionId
string
The unique identifier of the root entity, which nominally matches the public id field of the page.
stableVersionId
string
The unique identifier for the current version of the page.
id
string
Unique identifier for the page.
name
string
Display name for the page.
group
array[object]
Group object containing information related to associated group for the page.
dirty
boolean
Boolean value returned if page is processing at the time of request.
rules
array[rules]
URL rules for the page.

Return list of all pages

Definition

GET https://app.pendo.io/api/v1/page
requests.get("https://app.pendo.io/api/v1/page")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/page \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/page"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

Example response

[{
        "createdByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "createdAt": 1505938241596,
        "lastUpdatedByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "lastUpdatedAt": 1505938241596,
        "kind": "Page",
        "rootVersionId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
        "stableVersionId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM-20170920201041.596687476",
        "id": "aJ0KOADQZVL5h9zQhiQ0q26PNTM",
        "name": "Dashboard",
        "color": "gray",
        "group": {
            "id": "_PENDO_DEFAULTGROUP_01_",
            "name": "Dashboard",
            "description": "",
            "color": ".groupColor01",
            "length": 6,
            "items": [],
            "createdByUser": {
                "id": "",
                "username": "",
                "first": "",
                "last": "",
                "role": 0
            },
            "createdAt": 1505937447295,
            "lastUpdatedByUser": {
                "id": "5197072786522112",
                "username": "[email protected]",
                "first": "Adam",
                "last": "Lohner",
                "role": 8
            },
            "lastUpdatedAt": 1505938327653
        },
        "dirty": false,
        "rules": [{
            "rule": "//*",
            "designerHint": "http://pendosandbox.com/",
            "parsedRule": "^https?://[^/]*/?(?:;[^#]*)?(?:\\?[^#]*)?(?:#.*)?$"
        }]
    },
    { page #2 },
    { page #3 }
]

Returns full list of pages

Details
Method GET
URI /api/v1/page
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Return list of specific pages

Definition

GET https://app.pendo.io/api/v1/page?={pageId_1},{pageId_2},{...}
requests.get("https://app.pendo.io/api/v1/page", params = "{pageId_1},{pageId_2},{...}")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/page?id=aJ0KOADQZVL5h9zQhiQ0q26PNTM \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/page"
params = {
    "id": "aJ0KOADQZVL5h9zQhiQ0q26PNTM"
}
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers, params = params)

Example response

 [
  { page #1 details },
  { page #2 details },
  { ... }
]

Instead of returning all pages, you can specify which pages you’d like returned by adding the page Id to the request.

Details
Method GET
URI /api/v1/page/{pageId}
Parameters {pageId} - id of the page to return. Multiple comma separated ids may be used.
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Report

Report endpoint

https://app.pendo.io/api/v1/report

The reports API works with Visitor or Account reports that have been created in your subscription. The {reportId} referenced below can be found at the end of the URL when viewing a report within the app: https://app.pendo.io/visitorlist/{reportId}. Visitor and Account reports can managed from the Visitor or Account report tabs.

NOTE: The report endpoint cannot be used to query paths or funnels reports.

The report object

Example response

[{
    "createdByUser": {
        "id": "5197072786522112",
        "username": "[email protected]",
        "first": "Adam",
        "last": "Lohner",
        "role": 8
    },
    "createdAt": 1506362416386,
    "lastUpdatedByUser": {
        "id": "5197072786522112",
        "username": "[email protected]",
        "first": "Adam",
        "last": "Lohner",
        "role": 8
    },
    "lastUpdatedAt": 1506362423556,
    "kind": "Report",
    "rootVersionId": "Gcs71tkJQe88CwiBKVQ9zd8sG1U",
    "stableVersionId": "Gcs71tkJQe88CwiBKVQ9zd8sG1U-20170925180023.556531973",
    "id": "Gcs71tkJQe88CwiBKVQ9zd8sG1U",
    "type": "",
    "name": "API Documentation Report",
    "shared": true,
    "definition": { ... },
    "aggregation": { ... },
    "lastRunAt": 1506363386484
}]
Attributes
createdByUser
user
The user that created the report.
createdAt
timestamp
The timestamp in milliseconds after the epoch when the report was created.
lastUpdatedByUser
user
The user that last updated the report.
lastUpdatedAt
timestamp
The timestamp in milliseconds after the epoch when the report was last updated.
kind
string
Returns the type of object. Report for example.
rootVersionId
string
The unique identifier of the root entity, which nominally matches the public id field of the report.
stableVersionId
string
The unique identifier for the current version of the report.
id
string
Unique identifier for the report.
name
string
Display name for the report.
shared
boolean
Returns true or false dependent on the reports visibility setting.
definition
array[definition]
Structure of the report, e.g., which columns were selected, which segment was applied, etc.
aggregation
array[aggregation]
See aggregation object definition.

The definition object

Example response

[{
  "config": {
    "columns": [],
    "segmentId": "everyone",
    "filters": [],
    "segments": []
  },
  "generator": "visitorList",
  "kind": "visitor",
  "timeSeries": {
    "type": "Last 30 Days",
    "start": "2017-08-01",
    "end": "2017-08-31"
  },
  "type": "List"
}]
Attributes
config
array
Returns the configuration options for the report such as the columns included, and any segment related information present.
generator
string
visitorList or accountList.
kind
string
Returns visitor or account dependent on the report kind.
timeSeries
array
The set timeSeries for the current report.
type
string
The type of report, for example “List”.

Return a list of public reports

Definition

GET https://app.pendo.io/api/v1/report
requests.get("https://app.pendo.io/api/v1/report")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/report \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/report"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

Example response

[{
        "createdByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "createdAt": 1506362416386,
        "lastUpdatedByUser": {
            "id": "5197072786522112",
            "username": "[email protected]",
            "first": "Adam",
            "last": "Lohner",
            "role": 8
        },
        "lastUpdatedAt": 1506362423556,
        "kind": "Report",
        "rootVersionId": "Gcs71tkJQe88CwiBKVQ9zd8sG1U",
        "stableVersionId": "Gcs71tkJQe88CwiBKVQ9zd8sG1U-20170925180023.556531973",
        "id": "Gcs71tkJQe88CwiBKVQ9zd8sG1U",
        "type": "",
        "name": "API Documentation Report",
        "shared": true,
        "definition": {
            "config": {
                "columns": [],
                "segmentId": "everyone",
                "filters": [],
                "segments": []
            },
            "generator": "visitorList",
            "history": [],
            "kind": "visitor",
            "timeSeries": {
                "type": "Today"
            },
            "type": "List"
        },
        "aggregation": {
            "fields": [{
                "type": "string",
                "title": "Visitor ID",
                "field": "visitorId"
            }],
            "pipeline": [{
                    "source": {
                        "events": null,
                        "timeSeries": {
                            "period": "dayRange",
                            "first": "now()",
                            "last": "now()"
                        }
                    }
                },
                {
                    "identified": "visitorId"
                },
                {
                    "group": {
                        "group": [
                            "visitorId"
                        ]
                    }
                },
                {
                    "select": {
                        "visitorId": "visitorId"
                    }
                }
            ]
        },
        "lastRunAt": 1506362423429
    },
    {},
    {}
]

Returns an array of JSON objects representing all public reports for a subscription.

Details
Method GET
URI /api/v1/report
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body

Return report contents as array of JSON objects

Definition

GET https://app.pendo.io/api/v1/report/{reportId}/results.json
requests.get("https://app.pendo.io/api/v1/report/{reportId}/results.json")

Example request

curl -X GET \
https://app.pendo.io/api/v1/report/Gcs71tkJQe88CwiBKVQ9zd8sG1U/results.json \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/report/Gcs71tkJQe88CwiBKVQ9zd8sG1U/results.json"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

Example response

[{
        "visitorId": "12"
    },
    {
        "visitorId": "4"
    },
    {
        "visitorId": "45"
    },
    {
        "visitorId": "63"
    },
    {
        "visitorId": "NaN"
    }
]

Returns a list of JSON objects.

Details
Method GET
URI /api/v1/report/{reportId}/results.json
Parameters reportId - ID of the report
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body
404: The report in question was not found.

Return report contents as csv

Definition

GET https://app.pendo.io/api/v1/report/{reportId}/results.csv
requests.get("https://app.pendo.io/api/v1/report/{reportId}/results.csv")

Example request

curl -X GET \
https://app.pendo.io/api/v1/report/8JsdfvwlY_Fx2uAHUsdfqOsYVXE/results.csv \
  -H 'content-type: text/csv' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/report/Gcs71tkJQe88CwiBKVQ9zd8sG1U/results.csv"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "text/csv"
}
response = requests.get(url, headers = headers)

Example response

Visitor ID
12
4
45
63
NaN
Details
Method GET
URI /api/v1/report/{reportId}/results.csv
Parameters reportId - ID of the report
Request Headers content-type: text/csv
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body
404: The report in question was not found.

Visitor

Visitor endpoint

https://app.pendo.io/api/v1/visitor

The visitor endpoint allows you to retrieve visitor specific details by supplying a visitor ID as part of your request. The {visitorId} referenced below can be found on the visitors list page or at the end of the url when viewing a visitor details page.

The visitor object

Example response

{
    "id": "4",
    "email": "",
    "accountIds": [
        "Epsilon united"
    ],
    "metadata": {
        "agent": {
            "email": "[email protected]",
            "ipaddress": "204.16.137.138",
            "language": "en_US"
        },
        "auto": {
            "accountid": "Epsilon united",
            "accountids": [
                "Epsilon united"
            ],
            "firstvisit": 1506351511034,
            "id": "4",
            "idhash": 4088798008,
            "lastbrowsername": "Chrome",
            "lastbrowserversion": "60.0.3112",
            "lastoperatingsystem": "Mac OS X",
            "lastservername": "pendosandbox.com",
            "lastupdated": 1506358391050,
            "lastuseragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
            "lastvisit": 1506358390891,
            "nid": 4
        }
    },
    "accountId": "Epsilon united"
}
Attributes
id
string
Unique identifier for the visitor.
accountIds
string
All Account ID associations for the visitor.
accountId
string
The Account ID last associated with the visitor.

Get visitor by ID

Definition

GET https://app.pendo.io/api/v1/visitor/{visitorId}
requests.get("https://app.pendo.io/api/v1/visitor/{visitorId}")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/visitor/4 \
  -H 'content-type: application/json' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/visitor/4"
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/json"
}
response = requests.get(url, headers = headers)

Example response

{
    "id": "4",
    "email": "",
    "accountIds": [
        "Epsilon united"
    ],
    "metadata": {
        "agent": {
            "email": "[email protected]",
            "ipaddress": "204.16.137.138",
            "language": "en_US"
        },
        "auto": {
            "accountid": "Epsilon united",
            "accountids": [
                "Epsilon united"
            ],
            "firstvisit": 1506351511034,
            "id": "4",
            "idhash": 4088798008,
            "lastbrowsername": "Chrome",
            "lastbrowserversion": "60.0.3112",
            "lastoperatingsystem": "Mac OS X",
            "lastservername": "pendosandbox.com",
            "lastupdated": 1506358391050,
            "lastuseragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
            "lastvisit": 1506358390891,
            "nid": 4
        }
    },
    "accountId": "Epsilon united"
}

Gets a visitor object using an Visitor ID.

Details
Method GET
URI /api/v1/visitor/{visitorId}
Parameters visitorId - URL encoded visitor id or b64_XXXX, where XXXX is a URL-safe base64 encoded visitor Id
Request Headers content-type: application/json
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: Response is sent as body
404: Error while getting visitor, no such entity found

Get visitor history for a time period

Definition

GET https://app.pendo.io/api/v1/visitor/{id}/history?starttime={starttime}
requests.get("https://app.pendo.io/api/v1/visitor/{visitorId}/history", params = "starttime={starttime}")

Example request

curl -X GET \
  https://app.pendo.io/api/v1/visitor/4/history?starttime=1506341326000 \
  -H 'content-type: application/x-www-form-urlencoded' \
  -H 'x-pendo-integration-key: 63bd1cda-db5a-4a2b-633b-37b8b0c5462c'
import requests
url = "https://app.pendo.io/api/v1/visitor/4/history"
params = {
    "starttime": "1506341326000"
}
headers = {
    'x-pendo-integration-key': "63bd1cda-db5a-4a2b-633b-37b8b0c5462c",
    'content-type': "application/x-www-form-urlencoded"
}
response = requests.get(url, headers = headers, params = params)

Example response

[{
        "type": "untagged",
        "ts": 1506351480000,
        "parsedUserAgent": {
            "name": "Chrome",
            "version": "60.0.3112",
            "os": "Mac OS X"
        },
        "duration": 120000,
        "lastTs": 1506351600000,
        "untaggedUrl": "http://pendosandbox.com/index.html"
    },
    {
        "type": "feature",
        "ts": 1506351551911,
        "uri": "://app.pendo.io/api/s/5335432811773952/feature/OFjRasLtgMG8_74hpiXdzVD7PH8",
        "parsedUserAgent": {
            "name": "Chrome",
            "version": "60.0.3112",
            "os": "Mac OS X"
        },
        "featureId": "OFjRasLtgMG8_74hpiXdzVD7PH8"
    },
    {
        "type": "feature",
        "ts": 1506351555327,
        "uri": "://app.pendo.io/api/s/5335432811773952/feature/DZc-w_WWNR_ia-SgtnF9yLntPds",
        "parsedUserAgent": {
            "name": "Chrome",
            "version": "60.0.3112",
            "os": "Mac OS X"
        },
        "featureId": "DZc-w_WWNR_ia-SgtnF9yLntPds"
    },
    {
        "type": "page",
        "ts": 1506353640000,
        "uri": "://app.pendo.io/api/s/5335432811773952/page/aJ0KOADQZVL5h9zQhiQ0q26PNTM",
        "parsedUserAgent": {
            "name": "Chrome",
            "version": "60.0.3112",
            "os": "Mac OS X"
        },
        "duration": 60000,
        "lastTs": 1506353700000,
        "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM"
    },
    {
        "type": "page",
        "ts": 1506358380000,
        "uri": "://app.pendo.io/api/s/5335432811773952/page/aJ0KOADQZVL5h9zQhiQ0q26PNTM",
        "parsedUserAgent": {
            "name": "Chrome",
            "version": "60.0.3112",
            "os": "Mac OS X"
        },
        "duration": 60000,
        "lastTs": 1506358440000,
        "pageId": "aJ0KOADQZVL5h9zQhiQ0q26PNTM"
    }
]

Returns a summary of visitor activity for a 24 hour time period.

Details
Method GET
URI /api/v1/visitor/{id}/history?starttime={starttime}
Parameters id - URL encoded visitor id or b64_XXXX, where XXXX is a URL-safe base64 encoded visitor Id
starttime - Start time for historical data, in milliseconds since the epoch
Request Headers content-type: application/x-www-form-urlencoded
x-pendo-integration-key: <PENDO_INTEGRATION_KEY>
Status Codes 200: The visitor history is returned in the body as a JSON list of objects. An empty list means there was no activity in that time period
404: The visitor is unknown

Note: Visitor history is limited to the last 180 days.

Response

Page views

{
    "type": "page",
    "pageId": {pageId},
    "uri": {uri},
    "ts": {ts},
    "lastTs": {lastTs}
}

Untagged page views

{
    "type": "untagged",
    "untaggedUrl": {untaggedUrl},
    "ts": {ts},
    "lastTs": {lastTs}
}

Feature usage

{
    "type": "feature",
    "featureId": {featureId},
    "uri": {uri},
    "ts": {ts}
}

Guide views

{
    "type": "guide",
    "guideId": {guideId},
    "guideStepId": {guideStepId},
    "uri": {uri},
    "ts": {ts}
}

Each historical event is a JSON object, each with its own type-dependent fields.

Attributes
type
string
The type of object. Page for example.
(object)id
string
The associated unique identifier or untaggedUrl for the returned resource.
ts
timestamp
Milliseconds after the epoch that the event occurred. For pages, this is the first time the page was seen during consecutive usage.
lastTs
timestamp
Last time in consecutive usage that a page (or untagged page) was seen.
uri
string
API call to get the type-specific object associated with this event (not applicable to untagged pages).

Track

Track endpoint (server-side)

https://app.pendo.io/data/track

The track endpoint allows you record any actions your users perform, along with any properties that describe the action. Each action is known as an event. Each event has a name and properties. For example, a Registered event may have properties like plan or accountType.

The track object

Example body

{
  "type": "track",
  "event": "Registered",
  "visitorId": "unique-string-id",
  "accountId": "account-id-of-visitor",
  "timestamp": 1524069206000,
  "properties": {
    "plan": "Pro Annual",
    "accountType" : "Facebook"
  },
  "context": {
    "ip": "76.253.187.23",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",
    "url": "https://mypage.com/admin",
    "title": "My Page - Admin"
  }
}
Attributes
track
string
Must be “track” (required)
event
string
Name of the action that a user has performed (required)
visitorId
string
Unique string identifier for the visitor (required)
accountId
string
Unique string identifier for the account to which the visitor belongs (strongly recommended)
timestamp
date/time
time (in milliseconds after the epoch) that the event occurred (required)
properties
object
Free-form object of properties of the event (optional)
context
object
Object of information about a user browser session provided only when an event is being tracked on behalf of that browser session. This is not used if the event is being generated by JavaScript code inside the user browser session, nor for system events that are not associated with a browser session (such as an administrator enabling functionality for a subscription).
Additional context properties
ip
string
Current user’s IP address (recommended)
userAgent
string
User agent of the device making the request (recommended)
url
string
Url of the current page in the browser (optional)
title
string
Title of the current page in the browser (optional)

Send a track event

Definition

POST https://app.pendo.io/data/track
requests.post("https://app.pendo.io/data/track")

Example request

curl -X POST \
  https://app.pendo.io/data/track \
  -H 'x-pendo-integration-key: Your_trackEventSecret_Key' \
  -d '{
  "type": "track",
  "event": "Registered",
  "visitorId": "unique-string-id",
  "accountId": "account-id-of-visitor",
  "timestamp": 1524069206000,
  "properties": {
    "plan": "Pro Annual",
    "accountType" : "Facebook"
  },
  "context": {
    "ip": "76.253.187.23",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",
    "url": "https://mypage.com/admin",
    "title": "My Page - Admin"
  }
}'
import requests

url = "https://app.pendo.io/data/track"

payload = "{\"type\": \"track\",\"event\": \"Registered\",\"visitorId\": \"unique-string-id\",\"accountId\": \"account-id-of-visitor\",\"timestamp\": 1524069206000,\"properties\": {\"plan\": \"Pro Annual\",\"accountType\" : \"Facebook\"},\"context\": {\"ip\": \"76.253.187.23\",\"userAgent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36\",\"url\": \"https://mypage.com/admin\",\"title\": \"My Page - Admin\"}}"
headers = {
    'x-pendo-integration-key': "trackEventSecret",
    'Content-Type': "application/json",
    }

response = requests.request("POST", url, data=payload, headers=headers)
Details
Method POST
URI /data/track
Payload Properties type - track (required)
event - Name of the action that a user has performed (required)
visitorId - Current user’s visitor Id (required)
accountId - Current users’s account Id (strongly recommended)
timestamp - time (in milliseconds after the epoch) that the event occurred (required)
properties - Additional metadata about the event (optional)
context - Any session information including IP address, user agent, url, and title
Request Headers content-type: application/json
x-pendo-integration-key: <Pendo_trackEventSecret_Key>
Status Codes 200: Response is sent as body
400: Error unmarshalling track event data

Note: Your <Pendo_trackEventSecret_Key> is different from your x-pendo-integration-key or your Pendo Subscription API Key (which is embedded in your install snippet). To find your <Pendo_trackEventSecret_Key>, navigate to your Subscription Settings and choose your app. Under the "App Details," click on "Show" next to "Track Event Shared Secret."