Skip to content

Pipedrive

Paid add-on. Every submission creates or updates a person, then opens a lead attached to them.

This document describes what the module guarantees and what it refuses. The user guide gives the short version, under “Sending answers to Pipedrive”.

A lead has no pipeline

We have to start there, because this module’s plan asked to “create a lead in a chosen pipeline” and that is not possible.

At Pipedrive, a pipeline is a property of the deal, not of the lead. Leads live in the leads inbox, which has no columns. The plan also ruled deals out of V1 — so one could not be honoured without crossing the other.

What Pipedrive really offers for steering a lead are the owner and the labels: who it falls to, and how it is filtered. Those are therefore what the setting carries. It is an acknowledged substitution, rather than the request delivered approximately under a name that would have suggested something else.

Searching before creating, and that is half the module

Pipedrive has no upsert: no “create or update”, no external key, no automatic matching.

Without a prior search, every submission would create one more person. After a month, the same client appears twelve times in the file — and nobody notices before trying to write to them. It is the kind of defect that makes no noise and costs you the customer file.

The search is therefore exact and covers the address alone. A fuzzy search — the one the API does by default — would match camille@example.test with camille@other-company.test, and the module would write into somebody else’s record.

That is why the address field is required here when the API does not demand it: without it, no matching is possible.

A send in four calls, which picks up where it stopped

Search the organisation, create it, search the person, write them, create the lead: every step can succeed while the next fails.

The ids obtained are therefore recorded as soon as they are, and a retry skips what is already acquired. Without that, a third attempt would search for a person it had just created — and if the search failed for the same reason as the first time, it would create a second.

That is the difference from single-call modules: here partial state exists, and denying it would have produced duplicates on every failure.

The submissions screen therefore shows the three ids, and the diagnostic screen says how far each failed send had got. “Person created, lead refused” can be read; a bare failure does not say what is left to fix.

The organisation is a nicety, not a condition

If an organisation field is mapped, it is searched by name and then created. If that fails, the send continues: a lead without an organisation is still a usable lead, and losing the submission over a company name would be a bad trade.

One submission, one lead

UNIQUE (submission) on the tracking table, and a row claim — UPDATE … WHERE state <> 'sent' with a time lease — which decides which of two crossing tasks actually sends.

It counts double here: two concurrent tasks would create not just two leads, but two people — each having searched before the other had written.

It does not cover the rare case: the call succeeds at Pipedrive, the response is lost on the way. That is the service’s limit, and it is why the optional reference field exists: the slf-<site>-<number> reference written on the lead does not prevent the duplicate, it makes it findable with a search.

Pipedrive answers 200 while saying no

Every response carries a success boolean, and a request refused for an invalid value regularly arrives with a success HTTP code and {"success": false, "error": "…"}.

Trusting the code would have counted as created people that Pipedrive refused, and the client would have seen it only by comparing their figures.

The ids are not all of the same kind

People and organisations carry numeric ids; leads carry UUIDs.

The distinction is not a curiosity: a bare cast would turn an unexpected value into 0, and Pipedrive reads 0 as an id, not as an absence. A lead would have gone out attached to person number zero. The check therefore precedes the conversion, and a person id that is not a number stops the send rather than producing a false record.

The same check applies to the owner and the labels, entered at form level: Pipedrive refuses the whole record on a non-numeric value.

The API’s address arrives over the network

That is Pipedrive’s particularity. oauth.pipedrive.com carries the authorisation; the API lives on the company’s domain — mycompany.pipedrive.com — which Pipedrive returns at token exchange under the name api_domain.

That address therefore comes from a network response, and it is the one we will then call with an access token. A tampered response must not be able to redirect subsequent submissions to a server of its choosing: it is checked against the .pipedrive.com suffix and the https scheme, and refused otherwise.

The leading dot in the suffix is deliberate. Without it, attacker-pipedrive.com would pass the check — that is the classic fault of this kind of list, and it does not show on reading.

A connection with no acceptable domain is not held to be established: a token you do not know where to use is not a connection.

The scopes, and those we did not ask for

contacts:full to write people and organisations, leads:full to create the lead, search:read to find a person again — without which every submission would create one more — and users:read to offer the list of owners on screen rather than making someone type a numeric id.

Not deals:full, which would have given write access to every deal in the account. An excess scope changes nothing as long as nothing goes wrong, and changes everything the day something does.

The secret travels in the header

Pipedrive expects the application’s authentication in Basic — the id/secret pair encoded in Authorization — where Google, Zoho and HubSpot take it in the form body. That is not a matter of style: a secret placed in the body is answered invalid_client with nothing to indicate where the error is.

What is not attempted, and what is retried

Nothing is scheduled if the connection is missing, if the name or address field is not designated, or if the form’s condition is not met. A submission marked as spam does not go out, even if the task was already queued. An empty name is a definitive refusal written before any call — Pipedrive would refuse it while talking about a property, not about the form field.

Definitive refusals are not replayed. 429 and 5xx are, at 1, 5 then 30 minutes. The distinction counts more here than elsewhere: a Pipedrive account has a daily call budget on top of the per-second limit, and hammering a definitive refusal consumes it for nothing — four calls every time.

A 401 earns a session renewal, requested once for everything that follows and not at every step.

A Pipedrive outage never blocks the submission. It is recorded, confirmed to the visitor and notified by email before this module is called on.

Resending opens a second lead

The resend button updates the person — they are found again by their address — but creates a new lead: Pipedrive can neither find nor replace the previous one, and the API only offers creation.

The screen says so before the click rather than letting you find out. The gesture remains useful: a restored right, a corrected owner, a scope granted after the fact.

The ids already acquired are kept by the resend: the person still exists, and searching for them would be a call for nothing.

What the log does not contain

Neither the request nor the response. Both carry the submission’s values: recording them would make the log a second copy, which would go off into backups and exports — where it would read as a technical trace when it describes a person. What remains is the HTTP code and the reason.

Schema

slf_pipedrive_leads: one row per submission, with the organisation, person and lead ids, the reference, the state, the reason for the last problem and the number of attempts. It disappears with the submission; the record at Pipedrive stays — it belongs to the CRM.

The connection lives in an option, tokens encrypted with a key of the integration’s own. The API domain is kept there in clear: it is not a secret, and it is the first thing to look at when sends are going nowhere.

What V1 does not do

No deal, no activity, no product. No reading from the CRM, no reverse synchronisation: the flow goes from the site to Pipedrive, and the reverse would turn a public WordPress site into a doorway onto the customer file.

No updating of an existing lead either, since the API offers no means of doing so from a submission.