Skip to main content
RapidDev - Software Development Agency
replit-integrationsStandard API Integration

How to Integrate Replit with Pipedrive

To integrate Replit with Pipedrive, store your Pipedrive API token in Replit Secrets (lock icon πŸ”’) and call the Pipedrive REST API from your server-side code. Pipedrive uses a simple API token that authenticates all requests β€” no OAuth flow required. From Replit you can create deals, persons, organizations, and activities, set up webhook subscriptions for real-time event delivery, and build custom sales pipeline automation. Use Autoscale deployment for webhook receivers.

What you'll learn

  • How to store your Pipedrive API token securely in Replit Secrets and authenticate API requests
  • How to create and manage deals, persons, and organizations using the Pipedrive REST API
  • How to set up Pipedrive webhook subscriptions to receive real-time deal and activity events
  • How to query pipeline stages and filter deals by stage, owner, and custom fields
  • How to build a Replit-hosted Express or Flask server as a Pipedrive automation layer
Book a free consultation
4.9Clutch rating ⭐
600+Happy partners
17+Countries served
190+Team members
Intermediate18 min read20 minutesMarketingMarch 2026RapidDev Engineering Team
TL;DR

To integrate Replit with Pipedrive, store your Pipedrive API token in Replit Secrets (lock icon πŸ”’) and call the Pipedrive REST API from your server-side code. Pipedrive uses a simple API token that authenticates all requests β€” no OAuth flow required. From Replit you can create deals, persons, organizations, and activities, set up webhook subscriptions for real-time event delivery, and build custom sales pipeline automation. Use Autoscale deployment for webhook receivers.

Sales Pipeline Automation from Replit with the Pipedrive API

Pipedrive's visual pipeline is one of the most intuitive CRM interfaces for sales teams, and its REST API exposes the same data model in a clean, consistently structured way. Every core entity β€” deals, persons, organizations, activities, products β€” follows the same request and response pattern, making Pipedrive one of the easiest CRMs to build integrations against. Simple API token authentication (no OAuth flow) means you can go from zero to first API call in minutes rather than the 45-minute setup that enterprise CRMs like Dynamics 365 require.

From Replit, the most valuable Pipedrive integration patterns are lead ingestion (automatically creating deals from web forms, ads, or external tools), pipeline event automation (triggering actions in other systems when deals advance stages), and activity management (creating follow-up tasks, calls, and emails programmatically). These patterns eliminate manual data entry for your sales team and ensure every lead is captured in the pipeline without human intervention.

Pipedrive's webhook system delivers real-time events to your Replit server when deals move through stages, deals are won or lost, new persons are created, or activities are completed. This event-driven architecture lets you build rich integrations β€” notify Slack when a deal is won, create a contract in DocuSign when a deal moves to the closing stage, or update an accounting system when a new client is added. For webhook delivery to work reliably, your Replit app must be deployed (not running in development mode, which goes offline when you close your browser).

Integration method

Standard API Integration

Pipedrive integrates with Replit through Pipedrive's REST API v1 using API token authentication. All requests include your API token as a query parameter or Authorization header. Your Replit backend creates and updates deals, persons, and organizations, and listens for Pipedrive webhook events that fire when deal stages change, new leads arrive, or activities are completed. The Pipedrive API is consistently structured across all entity types, making it straightforward to extend once you understand the pattern.

Prerequisites

  • A Replit account with a Node.js or Python Repl ready
  • A Pipedrive account β€” free trial available at pipedrive.com
  • Your Pipedrive API token from Settings β†’ Personal Preferences β†’ API in Pipedrive
  • For webhooks: your app deployed with a stable HTTPS URL (https://yourapp.replit.app)

Step-by-step guide

1

Get Your Pipedrive API Token and Store It in Replit Secrets

Pipedrive API tokens are user-specific β€” each Pipedrive user has their own API token that grants access to their account's data according to their permission level. For integration purposes, create a dedicated Pipedrive user account for your automation (e.g., 'Integration Bot') with appropriate permissions, and use that user's token. This way, if the token needs to be rotated, only the bot user is affected, and activities created via the API are attributed to a recognizable bot user rather than a personal account. To find your API token: log into Pipedrive β†’ click your avatar/name in the top right β†’ Settings β†’ Personal Preferences β†’ scroll down to 'API' section or navigate to the API tab. Your token is a 40-character alphanumeric string. Copy it. You will also need your Pipedrive company domain, which appears in your Pipedrive URL as: https://{company}.pipedrive.com. Some API calls require this subdomain. Open your Replit project and click the lock icon (πŸ”’) in the sidebar. Add: PIPEDRIVE_API_TOKEN: your 40-character Pipedrive API token. PIPEDRIVE_COMPANY_DOMAIN: your company subdomain (the part before .pipedrive.com). Pipedrive's API token provides the same access as the user who owns it β€” treat it as a password. Replit's Secret Scanner will flag the token if it detects it in source code.

check-pipedrive-secrets.js
1// check-pipedrive-secrets.js
2const required = ['PIPEDRIVE_API_TOKEN'];
3for (const key of required) {
4 if (!process.env[key]) {
5 throw new Error(`Missing: ${key}. Add it in Replit Secrets (lock icon πŸ”’).`);
6 }
7}
8const token = process.env.PIPEDRIVE_API_TOKEN;
9if (token.length !== 40) {
10 console.warn(`Warning: Pipedrive API tokens are typically 40 characters. Got ${token.length}.`);
11}
12console.log('Pipedrive secrets configured.');
13console.log('Token prefix:', token.slice(0, 8) + '...');

Pro tip: For production integrations, create a dedicated Pipedrive user account (e.g., api-bot@yourcompany.com) to own the API token. This makes it easy to identify API-created records, keep the token from affecting a real user's account, and revoke access without disrupting anyone.

Expected result: PIPEDRIVE_API_TOKEN is set in Replit Secrets. The verification script confirms the token length and prints without errors.

2

Create Deals, Persons, and Organizations with Node.js

The Pipedrive REST API base URL is https://api.pipedrive.com/v1. Authentication is via the api_token query parameter appended to every request URL, or as a Bearer token in the Authorization header β€” use the header approach in production as it keeps the token out of server access logs. Pipedrive entities have a hierarchy: Persons and Organizations are contacts; Deals are sales opportunities linked to a Person and/or Organization and placed in a pipeline stage. Always create the Person first, then the Deal linked to that Person. The Pipedrive API consistently returns a wrapper object: { success: true, data: {...} } for single records and { success: true, data: [{...}] } for lists. Always check success before accessing data. Custom fields in Pipedrive are stored with hash keys (e.g., 'abc123' rather than a human-readable name). Find custom field hash keys in Pipedrive Settings β†’ Data Fields β†’ hover over a custom field to see its key, or call GET /v1/personFields or /v1/dealFields to list all fields with their keys. For Python examples, the pattern is identical using the requests library β€” the code is shown in the next step.

pipedrive-client.js
1// pipedrive-client.js β€” Create and manage Pipedrive entities
2const TOKEN = process.env.PIPEDRIVE_API_TOKEN;
3const BASE_URL = 'https://api.pipedrive.com/v1';
4
5async function pipedriveRequest(method, endpoint, body = null, params = {}) {
6 const url = new URL(`${BASE_URL}${endpoint}`);
7 // Optionally use header auth instead: Authorization: Bearer {token}
8 url.searchParams.set('api_token', TOKEN);
9 Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
10
11 const options = {
12 method,
13 headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }
14 };
15 if (body) options.body = JSON.stringify(body);
16
17 const response = await fetch(url.toString(), options);
18 const data = await response.json();
19
20 if (!data.success) {
21 throw new Error(`Pipedrive error: ${data.error || JSON.stringify(data)}`);
22 }
23 return data.data;
24}
25
26// Create a Person (contact)
27async function createPerson(name, email, phone, orgId = null) {
28 return pipedriveRequest('POST', '/persons', {
29 name,
30 email: [{ value: email, primary: true }],
31 phone: [{ value: phone, primary: true }],
32 org_id: orgId
33 });
34}
35
36// Create an Organization
37async function createOrganization(name, address = '') {
38 return pipedriveRequest('POST', '/organizations', { name, address });
39}
40
41// Create a Deal
42async function createDeal(title, personId, orgId = null, stageId = null, value = null) {
43 return pipedriveRequest('POST', '/deals', {
44 title,
45 person_id: personId,
46 org_id: orgId,
47 stage_id: stageId, // null = first stage of default pipeline
48 value, // deal value in account currency
49 currency: 'USD'
50 });
51}
52
53// Add a note to a deal
54async function addNote(dealId, content) {
55 return pipedriveRequest('POST', '/notes', {
56 deal_id: dealId,
57 content
58 });
59}
60
61// Get pipeline stages
62async function getStages(pipelineId = null) {
63 const params = pipelineId ? { pipeline_id: pipelineId } : {};
64 return pipedriveRequest('GET', '/stages', null, params);
65}
66
67// Get deals by stage
68async function getDealsByStage(stageId, status = 'open') {
69 return pipedriveRequest('GET', '/deals', null, {
70 stage_id: stageId,
71 status // 'open', 'won', 'lost', 'deleted', 'all_not_deleted'
72 });
73}
74
75// Example: create a complete lead
76(async () => {
77 try {
78 // 1. Create the organization
79 const org = await createOrganization('Acme Corp', '123 Main St, New York, NY');
80 console.log('Org created:', org.id, org.name);
81
82 // 2. Create the person
83 const person = await createPerson('Jane Smith', 'jane@acme.com', '+15551234567', org.id);
84 console.log('Person created:', person.id, person.name);
85
86 // 3. Create the deal
87 const deal = await createDeal('Acme Corp β€” Enterprise License', person.id, org.id, null, 15000);
88 console.log('Deal created:', deal.id, deal.title);
89
90 // 4. Add a note
91 await addNote(deal.id, 'Inbound lead from website contact form. Interested in annual enterprise plan.');
92 console.log('Note added.');
93 } catch (err) {
94 console.error('Error:', err.message);
95 }
96})();
97
98module.exports = { createPerson, createOrganization, createDeal, addNote, getStages, getDealsByStage, pipedriveRequest };

Pro tip: Use stage_id: null when creating deals to place them in the first stage of the default pipeline automatically. Get the correct stage_id values for specific stages by calling GET /v1/stages first and looking up the stage name in the returned list.

Expected result: Running the script creates an organization, person, and linked deal in Pipedrive. All three appear in the Pipedrive interface under their respective sections. The note is visible on the deal's detail page.

3

Create Pipedrive Entities with Python

The Python Pipedrive client uses the requests library (pre-installed in most Replit Python environments). Authentication appends the api_token to all request URLs or uses a Bearer header. Response parsing checks the success field before returning the data. For Flask applications, the pipedrive request functions can be called directly from route handlers. For background jobs (e.g., syncing leads from a database every hour), call them from a scheduled task or thread. Error handling should distinguish between Pipedrive-reported errors (success: False with an error message) and network/HTTP errors. The PipedriveError below wraps both cases with a consistent interface. Pipedrive returns consistent data structures across entity types β€” create_person and create_deal follow exactly the same response pattern, making it easy to extend to any other entity type using the same pattern.

pipedrive_client.py
1# pipedrive_client.py β€” Pipedrive REST API client for Replit
2import os
3import requests
4
5TOKEN = os.environ['PIPEDRIVE_API_TOKEN']
6BASE_URL = 'https://api.pipedrive.com/v1'
7
8def pipedrive_request(method: str, endpoint: str, body: dict = None, params: dict = None) -> dict:
9 """Make an authenticated Pipedrive API request."""
10 url = f'{BASE_URL}{endpoint}'
11 all_params = {'api_token': TOKEN}
12 if params:
13 all_params.update(params)
14
15 response = requests.request(
16 method, url,
17 params=all_params,
18 json=body,
19 headers={'Content-Type': 'application/json'}
20 )
21 response.raise_for_status()
22 data = response.json()
23
24 if not data.get('success'):
25 raise Exception(f'Pipedrive error: {data.get("error", str(data))}')
26
27 return data['data']
28
29def create_person(name: str, email: str, phone: str = None, org_id: int = None) -> dict:
30 """Create a Person in Pipedrive."""
31 payload = {
32 'name': name,
33 'email': [{'value': email, 'primary': True}]
34 }
35 if phone:
36 payload['phone'] = [{'value': phone, 'primary': True}]
37 if org_id:
38 payload['org_id'] = org_id
39 return pipedrive_request('POST', '/persons', payload)
40
41def create_organization(name: str, address: str = None) -> dict:
42 """Create an Organization in Pipedrive."""
43 payload = {'name': name}
44 if address:
45 payload['address'] = address
46 return pipedrive_request('POST', '/organizations', payload)
47
48def create_deal(title: str, person_id: int = None, org_id: int = None,
49 value: float = None, stage_id: int = None) -> dict:
50 """Create a Deal in Pipedrive."""
51 payload = {'title': title, 'currency': 'USD'}
52 if person_id: payload['person_id'] = person_id
53 if org_id: payload['org_id'] = org_id
54 if value is not None: payload['value'] = value
55 if stage_id: payload['stage_id'] = stage_id
56 return pipedrive_request('POST', '/deals', payload)
57
58def add_note(deal_id: int, content: str) -> dict:
59 """Add a note to a deal."""
60 return pipedrive_request('POST', '/notes', {'deal_id': deal_id, 'content': content})
61
62def create_activity(deal_id: int, subject: str, activity_type: str, due_date: str) -> dict:
63 """Create a follow-up activity (call, email, task) linked to a deal."""
64 return pipedrive_request('POST', '/activities', {
65 'deal_id': deal_id,
66 'subject': subject,
67 'type': activity_type, # 'call', 'email', 'task', 'meeting'
68 'due_date': due_date # YYYY-MM-DD format
69 })
70
71if __name__ == '__main__':
72 org = create_organization('Acme Corp')
73 print(f'Org: {org["id"]} β€” {org["name"]}')
74
75 person = create_person('Jane Smith', 'jane@acme.com', '+15551234567', org['id'])
76 print(f'Person: {person["id"]} β€” {person["name"]}')
77
78 deal = create_deal('Enterprise License', person['id'], org['id'], 15000.0)
79 print(f'Deal: {deal["id"]} β€” {deal["title"]} (${deal["value"]})')

Pro tip: Activity types in Pipedrive are strings matching the type names visible in your account: 'call', 'email', 'task', 'meeting', 'lunch'. Custom activity types added by your admin also appear here. Use GET /v1/activityTypes to list all valid types for your account.

Expected result: Running the script creates an organization, person, and deal in Pipedrive via the Python client. All three entities appear in the Pipedrive web interface.

4

Set Up Pipedrive Webhooks to Receive Real-Time Events

Pipedrive webhooks deliver real-time notifications to your Replit server when data changes β€” deals move stages, new persons are created, activities are completed, or deals are won or lost. This event-driven model lets you build responsive automations that react instantly to sales activity. Pipedrive webhooks are configured via the API or in Settings β†’ Tools and integrations β†’ Webhooks β†’ Add webhook. Each webhook has a subscription URL (your deployed Replit endpoint), an event action (added, updated, deleted, merged, all), and an event object (deal, person, organization, activity, all). You can also filter by pipeline or user. Best practice for webhook setup: create webhooks via API on startup and delete them on shutdown (or use a single global webhook for all events and route by type). Store the webhook ID if you create them via API so you can manage them later. IMPORTANT: Pipedrive sends webhooks to your subscription URL as JSON POST requests. Your endpoint must return 200 within 15 seconds or Pipedrive marks the delivery as failed. Deploy as Autoscale or Reserved VM β€” development Repls go offline and cannot receive webhooks reliably. Pipedrive does not sign webhook payloads by default. Use a secret token in your URL path to prevent unauthorized requests to your endpoint.

pipedrive-webhook-server.js
1// pipedrive-webhook-server.js β€” Handle Pipedrive webhook events
2const express = require('express');
3const app = express();
4app.use(express.json());
5
6// Add a secret to your webhook URL in Pipedrive:
7// https://yourapp.replit.app/pipedrive/webhook/YOUR_SECRET
8const WEBHOOK_SECRET = process.env.PIPEDRIVE_WEBHOOK_SECRET || 'your-secret-token';
9
10app.post('/pipedrive/webhook/:secret', (req, res) => {
11 if (req.params.secret !== WEBHOOK_SECRET) {
12 return res.status(403).json({ error: 'Unauthorized' });
13 }
14
15 const { event, meta, current, previous } = req.body;
16 const { action, object } = meta || {};
17
18 console.log(`Pipedrive webhook: ${action} ${object}`);
19
20 if (object === 'deal') {
21 if (action === 'added') {
22 console.log('New deal created:', current.id, current.title);
23 console.log('Value:', current.value, current.currency);
24 // TODO: send Slack notification, create invoice, etc.
25
26 } else if (action === 'updated') {
27 // Check if deal was won
28 if (current.status === 'won' && previous?.status !== 'won') {
29 console.log('Deal WON:', current.title, 'Value:', current.value);
30 // TODO: trigger onboarding, notify finance team
31 }
32 // Check if stage changed
33 if (current.stage_id !== previous?.stage_id) {
34 console.log(`Deal stage changed: ${previous?.stage_id} β†’ ${current.stage_id}`);
35 // TODO: create follow-up activity, send email
36 }
37
38 } else if (action === 'deleted') {
39 console.log('Deal deleted:', current.id);
40 }
41
42 } else if (object === 'person') {
43 if (action === 'added') {
44 console.log('New person:', current.name, current.email?.[0]?.value);
45 }
46 } else if (object === 'activity') {
47 if (action === 'updated' && current.done) {
48 console.log('Activity completed:', current.subject, 'Deal:', current.deal_id);
49 }
50 }
51
52 // Always respond 200 quickly
53 res.status(200).json({ received: true });
54});
55
56// Register webhook via API on startup (optional β€” can also be done manually in Pipedrive UI)
57async function registerWebhook() {
58 const TOKEN = process.env.PIPEDRIVE_API_TOKEN;
59 const baseUrl = process.env.REPLIT_DEPLOYMENT_URL || 'https://yourapp.replit.app';
60 const subscriptionUrl = `${baseUrl}/pipedrive/webhook/${WEBHOOK_SECRET}`;
61
62 const response = await fetch(`https://api.pipedrive.com/v1/webhooks?api_token=${TOKEN}`, {
63 method: 'POST',
64 headers: { 'Content-Type': 'application/json' },
65 body: JSON.stringify({
66 subscription_url: subscriptionUrl,
67 event_action: 'all',
68 event_object: 'deal'
69 })
70 });
71 const data = await response.json();
72 if (data.success) {
73 console.log('Webhook registered, ID:', data.data.id);
74 } else {
75 console.warn('Webhook registration warning:', data.error);
76 }
77}
78
79app.listen(3000, '0.0.0.0', () => {
80 console.log('Pipedrive webhook server running on port 3000');
81 // registerWebhook(); // Uncomment after deploying
82});

Pro tip: Pipedrive's webhook payload includes both 'current' (the entity's current state) and 'previous' (its state before the change). This lets you detect exactly what changed β€” for example, comparing current.stage_id !== previous.stage_id to detect a stage transition rather than just any update.

Expected result: The webhook server starts on port 3000. After deploying and configuring the webhook URL in Pipedrive Settings, creating or updating a deal triggers the endpoint and logs the event type and deal details to the console.

Common use cases

Web Form to Pipeline Lead Ingestion

Automatically create Pipedrive persons and deals when web form submissions arrive. Instead of manually entering leads from website contact forms, demo requests, or ad landing pages, a Replit webhook receiver captures the form data, creates a Person with contact details and an associated Deal in the appropriate pipeline stage, and assigns it to the right sales rep based on territory or round-robin logic.

Replit Prompt

Build a webhook endpoint that receives contact form submissions (name, email, company, message), creates a Pipedrive Person with the contact details, creates a Deal linked to the person in the 'New Lead' stage, adds a note with the form message, and returns the Pipedrive deal ID for confirmation tracking.

Copy this prompt to try it in Replit

Deal Stage Change Automation

Trigger external actions when deals advance through pipeline stages. When a deal moves to 'Proposal Sent', automatically create a follow-up activity due in 3 days. When a deal is marked Won, send a congratulations message to Slack, create a new client record in your accounting system, and schedule an onboarding call. Pipedrive webhooks deliver these stage-change events in real time to your Replit server.

Replit Prompt

Create a webhook receiver that listens for Pipedrive deal stage changes, sends a Slack notification when a deal is Won including deal value and client name, creates a follow-up 'Onboarding Call' activity in Pipedrive due 7 days later, and logs the event to a database for reporting.

Copy this prompt to try it in Replit

CRM Data Sync and Reporting API

Build a custom reporting layer on top of Pipedrive that aggregates pipeline data for stakeholders who do not need full Pipedrive access. The Replit server queries the Pipedrive API for deals grouped by stage, owner performance metrics, and upcoming activities β€” then serves a simplified JSON API for a lightweight dashboard or weekly email digest.

Replit Prompt

Create an API endpoint that queries Pipedrive for all deals in the current month, groups them by stage and owner, calculates total pipeline value and average deal size per stage, and returns a summary JSON suitable for a sales performance dashboard.

Copy this prompt to try it in Replit

Troubleshooting

Pipedrive API returns { success: false, error: 'Unauthorized' } on all requests

Cause: The PIPEDRIVE_API_TOKEN in Replit Secrets is incorrect or has been rotated. Pipedrive API tokens are 40 characters β€” a shorter or longer value indicates the wrong field was copied.

Solution: In Pipedrive, navigate to your avatar β†’ Settings β†’ Personal Preferences β†’ API tab. Verify the token matches PIPEDRIVE_API_TOKEN in Replit Secrets exactly (no whitespace). If you have multiple workspaces, ensure you are using the token for the correct workspace.

typescript
1// Quick auth test
2fetch(`https://api.pipedrive.com/v1/users/me?api_token=${process.env.PIPEDRIVE_API_TOKEN}`)
3 .then(r => r.json())
4 .then(d => console.log('Auth test:', d.success ? `OK β€” ${d.data.name}` : `FAIL β€” ${d.error}`));

Pipedrive webhooks are not being received β€” events show as 'failed delivery' in Pipedrive settings

Cause: Your Replit app is in development mode and offline, or the webhook subscription URL does not match your deployed endpoint path including the secret token in the URL.

Solution: Deploy your app using Autoscale or Reserved VM to get a stable HTTPS URL. In Pipedrive Settings β†’ Tools and integrations β†’ Webhooks, verify the subscription URL matches your deployed endpoint exactly. Test the URL is reachable by making a manual POST to it with curl or a tool like Postman.

Deal is created but stage_id does not correspond to the expected pipeline stage

Cause: Stage IDs are numeric identifiers specific to each Pipedrive account β€” the same stage name has different IDs across different accounts. Hardcoding a stage ID from documentation or another account will not work.

Solution: Call GET /v1/stages to retrieve all stages with their IDs for your account. Use the stage_name to find the correct stage_id for your pipeline. Store the correct IDs in Replit Secrets or a config file rather than hardcoding them.

typescript
1// Fetch and print all pipeline stages
2fetch(`https://api.pipedrive.com/v1/stages?api_token=${process.env.PIPEDRIVE_API_TOKEN}`)
3 .then(r => r.json())
4 .then(d => d.data.forEach(s => console.log(`Stage ${s.id}: ${s.name} (Pipeline: ${s.pipeline_id})`)));

Custom field data is not saving on deals or persons

Cause: Custom fields in Pipedrive are identified by unique hash keys (e.g., 'a1b2c3d4') rather than human-readable names. Using the field label instead of the hash key silently drops the data.

Solution: Call GET /v1/dealFields or GET /v1/personFields to list all custom fields with their hash keys. Use the hash key (the 'key' property in the response) as the field name in your POST/PATCH requests, not the field label.

typescript
1// List all deal custom fields and their hash keys
2fetch(`https://api.pipedrive.com/v1/dealFields?api_token=${process.env.PIPEDRIVE_API_TOKEN}`)
3 .then(r => r.json())
4 .then(d => d.data.filter(f => f.edit_flag)
5 .forEach(f => console.log(`'${f.name}' β†’ key: '${f.key}'`)));

Best practices

  • Store PIPEDRIVE_API_TOKEN in Replit Secrets (lock icon πŸ”’) β€” the token grants the same access as the user who owns it, including the ability to delete all records
  • Create a dedicated Pipedrive user account (e.g., api-bot@yourcompany.com) for API token ownership so integration activities are clearly attributed and token rotation does not affect a real user
  • Always pass the api_token in the Authorization header as 'Bearer {token}' rather than as a URL query parameter to keep tokens out of server access logs
  • Fetch pipeline stage IDs dynamically rather than hardcoding them β€” stage IDs are account-specific and change if stages are deleted and recreated
  • Deploy as Autoscale or Reserved VM for webhook receivers β€” development Repls go offline when you close your browser, causing Pipedrive to mark webhook deliveries as failed
  • Use Pipedrive's 'current' and 'previous' webhook payload fields to implement precise change detection (e.g., only react to stage transitions, not all deal updates)
  • Add a secret token to your webhook URL path and verify it on every incoming request to prevent unauthorized access to your webhook endpoint
  • Implement retry logic with exponential backoff for Pipedrive API calls β€” the API has rate limits and occasionally returns 5xx errors that resolve on retry

Alternatives

Frequently asked questions

How do I find my Pipedrive API token?

In Pipedrive, click your avatar or name in the top-right corner β†’ Settings β†’ scroll to 'Personal Preferences' β†’ click the 'API' tab (or look for 'API token' on the page). Your 40-character token is shown there. Copy it to Replit Secrets as PIPEDRIVE_API_TOKEN. If you do not see an API tab, check that your account has API access enabled β€” some Pipedrive plans restrict API usage.

Does Pipedrive have a free plan that includes API access?

Pipedrive does not have a free tier, but offers a 14-day free trial with full API access. Paid plans start at the Essential tier, and all paid plans include REST API access. API call limits depend on your plan β€” higher plans have higher daily API request limits.

What is the difference between Pipedrive and HubSpot for API integration?

Pipedrive uses simple API token authentication (one secret, no OAuth), making it faster to integrate. HubSpot offers both API key and OAuth options but bundles many more objects and marketing features. Pipedrive's API is more focused on sales pipeline operations (deals, stages, activities), while HubSpot's API covers a much broader surface area including contacts, emails, forms, and marketing workflows.

What deployment type should I use for a Pipedrive webhook receiver on Replit?

Use Autoscale deployment for most Pipedrive webhook setups β€” deal and activity events are infrequent enough that Autoscale's occasional 1-3 second cold start is acceptable. Pipedrive marks a delivery as failed if your endpoint does not respond within 15 seconds, so even with cold start you have plenty of time. Use Reserved VM if you need guaranteed sub-second response times for real-time pipeline automation.

How do I create custom fields on Pipedrive entities via the API?

Custom field creation is done via the management APIs: POST /v1/dealFields to create a new custom field on deals, or POST /v1/personFields for person fields. The response includes the unique hash key for the new field. Use that hash key when reading or writing the custom field value in subsequent API calls β€” Pipedrive identifies custom fields by hash key, not by label name.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation β€” no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.