Crossdeck Docs
Dashboard

Connect Pipedrive — every sales touch on the same customer timeline as the website journey

Setup Pipedrive OAuth 2.0 · read-only · ~7 min read · Updated July 17, 2026

Connect your Pipedrive and every sales touch — deals, people, activities (calls, meetings, tasks) — lands on the same customer timeline as the website journey Crossdeck already captures. The connector reads Pipedrive on a schedule over OAuth 2.0 with read-only scopes, joins each record to a person by identity, and surfaces the result in People and the customer Journey — plus the Prism by Crossdeck card inside Pipedrive. Do one extra thing — stamp the Crossdeck customer id onto a Pipedrive custom field — and the match stops being “probably the same person” and becomes “provably the same person.” Crossdeck only ever reads. Nothing is written back to your Pipedrive.

TL;DR

What you get

Pipedrive is where your sales team's version of the customer lives — the deals, the calls, the meetings, the leads. Crossdeck already holds the product version: the anonymous first visit, the sign-up, the feature usage, the subscription, the errors they hit. On their own, each is half the picture. Connecting Pipedrive merges the two halves onto one timeline, keyed to one person.

Concretely, once connected:

Read-only, by design.

Crossdeck reads your Pipedrive; it does not write to it. No deals are created, no fields are overwritten, no contacts are mutated. The one write in this whole integration is one you make — stamping the Crossdeck ID onto a Person field from your backend (Step 2). That's your data, written by your code.

How the loop turns on — the event is the key

The integration has two halves, and it's worth being precise about which is which, because only one of them is automatic.

The half Crossdeck runs (automatic once you connect): the OAuth connection is read-only. Crossdeck reads the Persons, Deals and Activities that are already in your Pipedrive, joins them to the person's journey, and renders the card. Connecting does not create anything in Pipedrive — it can only read what's there.

The half you run (the “on switch”): records only reach Pipedrive because your backend puts them there, and that is triggered by an event you fire — the moment identity becomes real for you. That event is whatever fits your product: an enquiry-form submission, a sign-up, a login, a purchase. In that one event handler, your backend does two things: identifies the person in Crossdeck to get their cdcust_…, and creates or updates the Pipedrive Person (and Lead/Deal) with that cdcust_… stamped on the Crossdeck ID field.

That handler is the key that turns the engine on. Without it, nothing lands in Pipedrive for Crossdeck to read, so nothing appears on the card. With it, the whole loop runs on its own:

An event you fire   (enquiry submitted · sign-up · login · purchase)
  → your backend identifies the person in Crossdeck → gets their cdcust_…
  → your backend creates/updates the Pipedrive Person (+ Lead/Deal),
     stamping cdcust_… on the "Crossdeck ID" field
  → Crossdeck's read-only connector picks it up (Step 1 & 3)
  → the sales record joins the person's website & product journey
  → the Prism card shows the whole story
Connecting alone is not enough — you fire the event.

OAuth wires Crossdeck to read your Pipedrive; it never reaches back to create a lead when someone acts on your site. The line that creates the Pipedrive record (and stamps the id) lives in your event handler — Steps 2 and 3 below are exactly that handler. The Crossdeck SDK on your site (capturing the journey and giving you the cdcust_…) is the front of this; the Pipedrive write is the back of it.

Step 1 — Connect Pipedrive

In the Crossdeck dashboard, open Developers → Integrations → Pipedrive and click Connect. Crossdeck redirects you to Pipedrive's OAuth 2.0 authorize screen, where you approve the connection in Pipedrive's own UI under whichever company account you're signed into. There is no API token to generate and paste.

Crossdeck requests read-only scopes only:

Scope What it reads
deals:read Deals and their stage changes — the pipeline movement that becomes deal_stage_changed and lead_created.
contacts:read Persons and organizations — the identity anchors (email, and the stamped Crossdeck ID custom field) the connector joins on.
activities:read Activities — calls, meetings, tasks — and their completion state, which become activity_created and activity_completed.
mail:read Read scope reserved for mail-linked context. Mail-open events are not emitted yet — see What flows into the journey.

Approve, and Pipedrive hands Crossdeck an access token and refresh token. Crossdeck stores them in Google Cloud Secret Manager and the connector begins polling Pipedrive on a schedule — pulling deals, persons, and activities, and reconciling them onto the customer timeline. The Pipedrive card flips to Connected.

You can connect first and map the field later.

Connecting is enough to start seeing sales touches on the timeline — matched on email. The exact-match handshake (Step 2 and Step 3) is the upgrade from “probably” to “provably.” Do it when you're ready; nothing breaks in the meantime.

Step 2 — Stamp the Crossdeck ID onto a Pipedrive custom field

This is the handshake that makes the match exact. Email works as a fallback (Identity model), but email is soft — it changes, it's shared, it's mistyped, and Sign in with Apple's Private Relay hands you a relay address that won't match. An id you own on both sides is hard. So you carry the Crossdeck customer id into Pipedrive and put it on the Person.

Create (or choose) the custom field

In Pipedrive, go to Settings → Data fields → Person and add a custom field — a single-line text field named, say, Crossdeck ID. Pipedrive assigns it a 40-character hex field API key (e.g. a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2). You'll need that key in Step 3. Copy it now from the field's settings.

Get the Crossdeck id

The value you stamp is the Crossdeck customer id — the canonical cdcust_… handle for the person. Where you read it from depends on where the identity is anchored:

Authenticate the write with your own Pipedrive credentials

This write goes to your Pipedrive, so it uses your own Pipedrive credentials — separate from the read-only connection Crossdeck made in Step 1. Crossdeck's token is read-only and Crossdeck's; it can't and won't write on your behalf. Your backend authenticates itself to Pipedrive, two ways:

The call itself is Pipedrive's Persons endpoint — POST to create, PATCH to update — against your company domain, e.g. https://{yourcompany}.pipedrive.com/api/v2/persons (or https://api.pipedrive.com/v1/persons). You set the Crossdeck ID by its 40-character field key. Pipedrive's own references, so you don't have to hunt for them:

Mind the host ↔ path pairing — this is the one that trips people up. Pipedrive has two API hosts with different path prefixes, and you can't mix them: on api.pipedrive.com the path is /v1/… (e.g. /v1/persons, /v1/leads) — not /api/v1/…; on your company domain it's /api/v1/… or /api/v2/… (e.g. https://{yourcompany}.pipedrive.com/api/v1/leads). Calling api.pipedrive.com/api/v1/leads returns 404 Unknown method. So if your flow also creates a Lead, it is POST https://api.pipedrive.com/v1/leadsLeads API →.

Write it when your backend touches the Person

Whenever your backend creates or updates a Pipedrive Person — the moment a lead is captured, a trial converts, or a deal is opened — set the custom field to the Crossdeck id. This is your write, from your code, against your Pipedrive token; Crossdeck is not involved in it.

// your backend — upsert a Pipedrive Person with the Crossdeck ID stamped.
// CROSSDECK_ID_FIELD is the 40-char field API key from Step 2.
const CROSSDECK_ID_FIELD = "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"

async function upsertPipedrivePerson({ email, name, crossdeckId }) {
  const res = await fetch("https://api.pipedrive.com/v1/persons", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${PIPEDRIVE_ACCESS_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name,
      email: [{ value: email, primary: true }],
      // the custom field is keyed by its API key, value = the cdcust_… id
      [CROSSDECK_ID_FIELD]: crossdeckId,
    }),
  })
  return res.json()
}

// crossdeckId comes from your identify() call — the resolved cdcust_… handle.
await upsertPipedrivePerson({
  email: "[email protected]",
  name: "Dana Okafor",
  crossdeckId: "cdcust_9f3a7c21b0e4",
})
Custom fields are addressed by API key, not label.

In Pipedrive's REST API a custom field is set by its 40-character key, not its display name. That's why you copy the key in Step 2 — both your write here and Crossdeck's read in Step 3 refer to the same key. Renaming the field's label later changes nothing; the key is stable.

Persons typed in by hand

Not every Person is created by your backend — a rep will often just type someone into Pipedrive. That case is covered, and you don't have to do anything special:

So the rule of thumb: automate the stamp from your backend where you can (it scales); for one-off or manually-entered records, email carries them, and a hand-pasted id makes any single one exact.

Step 3 — Map the field in Crossdeck

Now tell Crossdeck which field holds the id. In the Pipedrive integration settings in the dashboard, paste the custom field API key from Step 2 into Crossdeck ID field and save.

From that point, when the connector reads a Pipedrive Person, it looks at that field first. If it finds a Crossdeck id there, it resolves the exact person by that owned id — a deterministic join, no guessing. If the field is empty (or you haven't mapped it), the connector falls back to matching on the Person's email address.

What Crossdeck sees on the PersonHow it resolvesStrength
The mapped field holds a Crossdeck id Exact match on your owned id — deterministic. Provably the same person
Field empty / unmapped, email present Match on email against the identity graph. Probably the same person
No id, no matchable email Held as a Pipedrive-only record until an anchor appears. Unresolved (not a duplicate customer)

That top row is the whole point of Steps 2 and 3. The difference between the first two rows is the difference between a report you can stake a renewal forecast on and one you have to caveat.

What flows into the journey

The connector reads Pipedrive on a schedule and emits these events onto the customer timeline, joined by identity. You'll see them in People, on the customer Journey, and on the Prism card:

EventFires when
lead_createdA new person, deal, or Pipedrive Lead is opened.
deal_stage_changedA deal moves between pipeline stages (including won / lost).
activity_createdAn activity — call, meeting, task — is scheduled or logged.
activity_completedAn activity is marked done.
email_sent / email_receivedA mailbox email to/from the person (correspondence — not opens; see below).

Each event carries its Pipedrive context (deal id, stage, activity type, and the person's organization / company when set) and attaches to the resolved customer — so a stage change sits on the same timeline as that person's page views, sign-up, and subscription. That cross-layer join is the thing no CRM-only or product-only tool can show you.

What's honest about the edges.

Email correspondence (sent / received) flows, but recipient open and click tracking is not exposed to apps by Pipedrive (it's their premium email feature), so Crossdeck surfaces messages, never opens. The Pipedrive Lead object emits lead_created once Pipedrive ships its OAuth scope for Leads (pending on their side) — until then, new deals already carry the lead signal, so nothing's missing. Webhooks (push instead of the scheduled poll) aren't available yet either. Don't build on opens or webhooks until they ship.

Identity model — one person, every key

Crossdeck's canonical identity is the cdcust. Its identity graph collapses every alias you hand it — the anonymous device, an email, and any durable rail or CRM id — into one person. Pipedrive is just another source feeding that graph, and it feeds it two keys with two strengths:

Both resolve to the same customer — never a duplicate. The exact id and the email fallback are two roads to the same cdcust_…. Adding the id later doesn't fork the person into two; it upgrades an email-matched person to a provably-matched one, in place. That's the guarantee: a sales touch and a product session for one human always land on one timeline.

Provably vs probably — and why it's your call.

Crossdeck won't invent a strong id it wasn't given. If you stamp the Crossdeck ID, you get deterministic matching; if you don't, you get email matching — honest about which it is, never dressing a soft match up as a hard one. The owned id is the difference, and putting it there is the one action that's yours to take.

Read-only & security

Troubleshooting

Connected, but sales touches aren't appearing on the timeline

The connector polls on a schedule, so allow a few minutes after connecting for the first pull. If touches still don't appear, the people aren't resolving to a customer — check that the Pipedrive Persons have either a mapped Crossdeck ID (Step 3) or an email that matches a known customer. A Person with neither is held as a Pipedrive-only record, not merged.

Deals show up under the wrong person, or as new people

Almost always the exact-match handshake isn't in place. Without the stamped id, the connector matches on email — so a Person whose Pipedrive email differs from the email Crossdeck knows (a work vs personal address, a relay address) resolves softly or not at all. Stamp the Crossdeck ID (Step 2) and map the field (Step 3) to make the match deterministic.

The Crossdeck ID field is set in Pipedrive but Crossdeck still matches on email

The field API key in the dashboard doesn't match the field you're writing to. Pipedrive custom fields are addressed by their 40-character key, not their label — re-copy the key from Settings → Data fields → Person and confirm it's the exact string both your backend write and the dashboard mapping use.

I expected a mail-open event and don't see one

Mail opens aren't emitted yet. The connector surfaces the four events in What flows into the journey only; the mail:read scope is reserved for future context. Nothing is wrong with your setup.

What's next


Read-only Pipedrive connector — OAuth 2.0 connect, scheduled poll for deals / persons / activities / organizations / email correspondence, exact-match on a stamped Crossdeck ID custom field with email fallback, and the Prism card endpoint (July 17, 2026). Email opens, the Lead-object scope, and webhooks are pending on Pipedrive's side. Related: Identify users, How identity works.

Using an AI assistant? Read this page as clean markdown — index.md — or the whole docs index at /docs/llms.txt.