How the Pipedrive adapter works

How the Pipedrive adapter works

Need some help? Contact us:

 

 

Like all our adapters, the Pipedrive adapter uses simple core concepts and common design patterns to ensure it is extensible and easy to understand.

Here is how it works:

In main, the “P” object will be used to call the methods defined in PIPEDRIVEclient.

local Config = component.fields() local P = PIPEDRIVEclient(Config)

Concepts used:

PIPEDRIVEclient creates the Pipedrive adapter framework.

PIPEDRIVEgetRecent and PIPEDRIVEgetDeal modules are defined in a metatable as methods and set to the P object. The API key passed to PIPEDRIVEclient is assigned to the new P table so that it can be used by the methods.

local MT={} MT.__index = {} MT.__index.custom = require 'PIPEDRIVE.PIPEDRIVEcustom' MT.__index.getRecent = require 'PIPEDRIVE.PIPEDRIVEgetRecent' MT.__index.getDeal = require 'PIPEDRIVE.PIPEDRIVEgetDeal' help.map{dir='PIPEDRIVE/help',methods=MT.__index} function PIPEDRIVEclient(T) P = {} setmetatable(P, MT) P.key = T.Key P.domain = T.PipedriveDomain return P end

Concepts used:

In main, the LastPollTime is checked and used to call PIPEDRIVEgetRecent for new Deals. If there are any new Deals they are serialized as a string and pushed to the component queue.

local LastPollTime = COUNTget('LastPollTime') local NextPollTime = os.time() -- Retrieve recent deals iguana.logInfo('Pulling recent items from '..os.date('%Y-%m-%d %H:%M:%S',LastPollTime)) local S, R = P:getRecent{LastPollTime = LastPollTime, items = 'deal', live=true} if R.data ~= json.NULL then for i=1,#R.data do queue.push{data=json.serialize{data=R.data[i]}} end end

Concepts used:

PIPEDRIVEgetRecent is passed the client object and the table of defined parameters.

PIPEDRIVEgetRecent formats the required endpoint and parameters to call PIPEDRIVEcustom to make the 'recents' API call. The COUNT Library returns 1 if the field is empty, therefore if the LastPollTime is 1, we set it to poll for deals from the last 24 hours.

If successful, then we check the response for an indication that there are more items to be collected. In the case that there are a large number of results, greater than the Pipedrive APIs limit (default ~500), then the Pipedrive API uses pagination to return results in pages with a flag to indicate where there are pages present and an index to the next item on the next page. This information is used to recursively call PIPEDRIVEgetRecent to compile all the results into a single table to be returned.

local function PIPEDRIVEgetRecent(T, C) local P = {} if C.LastPollTime == 1 then C.LastPollTime = os.time()-24*60*60 -- Default to 24 hours ago end P.since_timestamp = os.date('!%Y-%m-%d %H:%M:%S',C.LastPollTime) P.items = C.items P.start = C.index local S, R = T:custom({api='recents',parameters=P,live=C.live}) if S then if R.additional_data.pagination.more_items_in_collection then C.index = R.additional_data.pagination.next_start local NextS, NextPage = PIPEDRIVEgetRecent(T,C) for i=1,#NextPage.data do table.insert(R.data,NextPage.data[i]) end end end return S, R end return PIPEDRIVEgetRecent

Concepts used:

PIPEDRIVEcustom is a helper function designed to handle different API requests with Pipedrive.

It prepares the base Pipedrive URL, authorization details in the header, and any additional parameters to be passed in the URL of the request.

net.http.get{} is used to send the request to Pipedrive. The response is parsed and either the response or error response is returned.

local function PIPEDRIVEcustom(T, C) local Url = "https://"..T.domain..".pipedrive.com/api/v1/"..C.api -- Load access key if not C.parameters then C.parameters = {} end C.parameters.api_token = T.key -- Take into account if domain is nil if T.domain == '' then error('Missing Pipedrive domain',3) end -- Load any path parameters if C.pathParams then for k,v in pairs(C.pathParams) do Url = Url:gsub('{'..k..'}',v) end end trace(Headers, Url, C.parameters) local R, Code = net.http.get{ url=Url, headers=Headers, parameters=C.parameters, live=C.live } if (C.live ~= true) then return false, "notlive" end R = json.parse{data=R} if Code ~= 200 then return false, R else return true, R end end return PIPEDRIVEcustom

Concepts used:

The COUNT Library is used to set a new poll time in the component card custom field and set to poll each minute.

-- Update our last pull time COUNTset('LastPollTime',NextPollTime) -- Set component to continuously pull in new updates component.setTimer{delay=60000}

Concepts used:

PIPEDRIVEgetDeal is another example method of retrieving Deals in Pipedrive, this time querying for a specific Deal according to its ID in Pipedrive. At the end of main we invoke this example:

-- Get Deal using ID P:getDeal{id=4, live=true}

PIPEDRIVEgetDeal is passed the client object and the table of defined parameters. It calls PIPEDRIVEcustom to with the required endpoint and parameters make the 'deal/{id}' API call.

Here we can also see how the path parameters are passed to PIPEDRIVEcustom. The api endpoint path is passed as deal/{id} with a table of path parameters which is used by PIPEDRIVEcustom to put in deal ID into the api endpoint.

local function PIPEDRIVEgetDeal(T, C) return T:custom{api='deals/{id}',pathParams={id=C.id},live=C.live} end return PIPEDRIVEgetDeal

Concepts used:

Thats it! You can easily extend the functionality based on your needs by creating new Pipedrive methods using their API documentation: https://developers.pipedrive.com/docs/api/v1.