For CRM providers

Want to integrate with Pruuv?

Your customers' CRM pipeline is marketing gold. Expose a few standard endpoints and Pruuv turns every lead and stage change into funnel analytics and ad conversions for them — one-click setup, zero engineering on their side.

Attio, HubSpot, Salesforce, Pipedrive & ZendeskRead-onlyReal-time or 15-min syncWe never write to your CRM
app.pruuv.io/settings/data-source
Connect
2Map
3Sync

Map your pipeline stages

Found 1 pipeline · 5 stages in Attio · previewing 3 records

CRM stagePruuv funnel step
Lead InLead
QualifiedQualified lead
Proposal SentOpportunity
WonDeal · revenue
LostNot tracked
updated_at cursor: 2026-08-05T09:14ZContinue

CRMs on Pruuv

Attio
HubSpot
Salesforce
Pipedrive
Zendesk

Attio, HubSpot, Salesforce, Pipedrive and Zendesk — all live on Pruuv today.

The integration your users see

The one-click experience you give your users

Three screens, no code, no CSV exports. Everything below runs on the four capabilities in the spec.

01

Connect

Your customer pastes a workspace API key, or signs in with OAuth. We verify it and store it encrypted — they never touch code.

GET /v2/self → 200 workspace_id
02

Map

Pruuv auto-discovers their pipeline and stages; they map each stage to a Pruuv funnel step, with a live 3-record preview.

GET /v2/objects/deals/attributes
03

Sync

They choose poll-every-15-minutes or real-time — where Pruuv programmatically creates a read-only webhook inside your CRM for them. No manual setup.

POST /v2/webhooks → record.updated

Integration spec

Four capabilities. That's the whole contract.

If your API can do these four things, Pruuv can ship a one-click connector for your customers. Endpoints below are the Attio implementation, for reference.

Authenticated API access

A workspace-scoped credential plus a cheap "who am I" call so we can verify a key the moment it's pasted.

Reference: Attio
GET /v2/self
Authorization: Bearer <token>
→ 200 { workspace_id, scopes }
records: readobject config: readwebhooks: read-write

Pipeline & schema discovery

Enumerate pipelines and their stages in display order, so mapping is a dropdown instead of a support ticket.

Reference: Attio
GET /v2/objects/{object}/attributes
→ pick the status attribute
GET .../attributes/{id}/statuses

Incremental record read

Query records changed since a cursor, and fetch one by id. That is the whole backfill and catch-up story.

Reference: Attio
POST /v2/objects/{object}/records/query
filter { created_at: { $gte } }
GET .../records/{id}

Webhook subscriptions

Create and delete a filtered, signed webhook programmatically — so real-time sync is a toggle, not a setup guide.

Reference: Attio
POST /v2/webhooks
events: record.created, record.updated
HMAC-SHA256 signed
DELETE /v2/webhooks/{id}

Example workflows

Five workflows, one pipe

Every CRM event — a new lead, a stage change, a lost deal, a first-time backfill, a double delivery — runs down the same normalise-map-post path. Here's what each looks like end to end.

record.created

A new lead lands

A prospect is created in your CRM's first pipeline stage.

  1. Your webhook fires — or our 15-minute poll finds the new record.
  2. We read the deal and resolve its stage to the customer's mapped funnel step.
  3. We post it into the funnel; dedup keeps re-sends idempotent.
  4. Identity recovery links the email and click-id back to earlier ad touches.

The lead appears in the agency's funnel, attributed to the campaign that drove it.

stage change

A deal advances through the pipeline

A deal moves Lead → Qualified → Proposal → Won.

  1. Each change arrives by webhook, or is caught at the next poll.
  2. We compare the deal's new stage to the highest stage already recorded.
  3. On a forward move we backfill every mapped stage in between, so progression is never gappy.
  4. Revenue stages carry the deal amount and currency.

The funnel shows a complete, ordered journey — and cost-per-stage stays correct.

revert

A deal slips back or is lost

A deal is moved to an earlier stage, or marked Lost.

  1. We detect the backward move against the recorded top stage.
  2. We post a revert for that reference, scoped to the affected stage.
  3. A security-definer RPC removes the reverted events; the cascade self-cleans.

Reporting reflects reality — no phantom conversions left behind.

backfill

First connection & historical backfill

A customer connects your CRM for the first time.

  1. We page historical records using the incremental cursor.
  2. Each deal is normalised and mapped exactly like a live change.
  3. The cursor advances to the newest record seen, so the next sync is a pure delta.

Their funnel is populated from day one — not just from connect-time forward.

dedup

The same deal syncs twice

A poll and a webhook both deliver the same change.

  1. Both resolve to the same reference and stage.
  2. The ingest route recognises the match and enriches, rather than duplicating.
  3. Newer fields — email, revenue, click-ids — fill in on the existing event.

One clean event per real-world milestone, getting richer over time.

Worked example

One record change, end to end

A deal moves to Proposal Sent in Attio. Here is exactly what crosses the wire — and how it lands in the funnel.

1 · Incoming webhook (Attio)
POST /api/webhooks/crm/{connectionId}
Attio-Signature: 9f2c… (HMAC-SHA256)

{
  "event_type": "record.updated",
  "id": { "record_id": "deal_8fa3…", "object_id": "deals" }
}
2 · Pruuv reads & normalises the deal
GET /v2/objects/deals/records/deal_8fa3…  → 200

CrmDeal {
  reference:  "deal_8fa3…"
  stage:      "Proposal Sent"
  updatedAt:  "2026-08-05T09:14:22Z"
  email:      "jo@acme.co.uk"
  revenue:    4200, currency: "GBP"
}
3 · Posted into the existing funnel ingest
POST /api/webhooks/funnel/{proposalStageId}
{ "reference": "deal_8fa3…",
  "data_timestamp": "2026-08-05T09:14:22Z",
  "email": "jo@acme.co.uk" }
→ dedup · identity recovery · attribution · progression fill

The same normalise-then-post path runs for both polling and webhooks, so every deal reuses the funnel’s dedup, identity recovery, attribution and revert — no CRM-specific ingest code.

Data flow

How the data flows

01 · Source

Record change in your CRM

A webhook fires, or our 15-minute poll picks up an updated record.

02 · Normalise

Pruuv normalises the deal

reference record idstage status nametimestamp updated_atemail contactrevenue amount
03 · Map

Stage → funnel step

The customer's saved mapping resolves the stage to one Pruuv funnel step.

04 · Post

Into the funnel

Dedup on reference · identity recovery · attribution to ad, campaign and creative · revert on backward move.

Read-only. One read-only webhook. We never write back to your CRM.

Under the hood

How the sync actually works

The connector is thin by design. Three mechanisms carry everything: how we authenticate, how we poll, and how we go real-time.

Auth · what we need

Two ways in

  • A workspace-scoped API key — pasted once, verified with a who-am-I call, and stored as an encrypted vault secret (never in plaintext, never in a column).
  • OAuth 2.0 for providers that require it — the same connect flow, with tokens refreshed automatically.
  • Least privilege: read on records and object config; read-write on webhooks only when real-time is switched on.

Polling · every 15 min

Deltas, not dumps

  • We keep a per-connection cursor — the newest record timestamp seen — and only ask for what changed since.
  • Results are sorted and paginated; we walk pages until the cursor is caught up.
  • Expose a real updated_at so stage changes move the timestamp — created_at alone only catches brand-new records.
  • We batch and back off; a 15-minute cadence is gentle on your rate limits.

Webhooks · real-time

We set them up, you sign them

  • When a customer chooses real-time, Pruuv creates the webhook in your CRM for them — filtered to the deals object, subscribed to create and update.
  • Every delivery is HMAC-SHA256 signed with a per-subscription secret; we reject anything that fails verification.
  • Acknowledge with a 2xx within a few seconds — we own retries, backoff and replay.
  • Switching back to polling, or disconnecting, deletes the subscription automatically.
Verify a delivery
const sig = req.headers['x-signature']
const digest = hmacSha256(rawBody, secret) // hex
if (!timingSafeEqual(sig, digest)) return 401
// verified → 200, we take it from here

Field notes

What makes a great integration

The difference between a connector that works and one that quietly drifts out of sync.

Expose a real updated_at

Not just created_at. Polling only catches stage changes if the timestamp moves when the record does.

Stable, unique record ids

We use the id as the funnel reference — it powers dedup and revert-on-backward-move.

Pipeline stages in order

Display order tells us what "forward" means, so a moved deal reads as progress, not noise.

HMAC-signed deliveries

A shared secret per subscription lets us reject anything we can't verify.

Return 2xx fast

Acknowledge and move on — we handle retries, backoff and replay on our side.

FAQ

Questions CRM teams ask

Do you ever write to our CRM?

No. We read records and — only for real-time — create one read-only webhook. Nothing is ever written back to your CRM.

How long does an integration take to build?

Days, not months, once your API covers the four capabilities. Pruuv writes and maintains the adapter — you build nothing on your side.

Which authentication do you support?

A workspace-scoped API key, and OAuth 2.0 for providers that require it — both flow through the same one-click connect.

How fresh is the data?

Real-time when the customer enables webhooks, otherwise polled every 15 minutes. Both paths share the same normalisation and dedup.

How do you treat our rate limits?

Cursor-based deltas, pagination and batching, with backoff and resume. We only ever pull what changed.

What about security and PII?

Credentials live in an encrypted vault as secret references, webhook deliveries are signature-verified, and we request least-privilege scopes.

What data do you actually read?

A deal's stable id, its pipeline stage, a change timestamp, the contact email and — on revenue stages — the amount. Each maps to a funnel stage the customer chooses.

Who are the mutual customers?

Digital marketing agencies and their clients, who use Pruuv to tie CRM outcomes back to ad spend.

Get your CRM on Pruuv.

Send us your API docs and we'll scope a one-click integration — days, not months.