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:
main first calls PIPEDRIVEclient, passing the Pipedrive API key and domain from custom fields
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 adapter framework by assigning methods to a metatable
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:
main checks the last time Deals were retrieved and calls PIPEDRIVEgetRecent for recent Deals to be queued
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 prepares the Pipedrive API for PIPEDRIVE custom to get the recent Deals
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 takes in any API request parameters to make a request and return the response
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:
After querying for recent Deals, the LastPollTime is updated in the component card and set to poll again every minute
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 gets the Deal by using the provided ID.
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.