Pipedrive integration
Send booking and lead data from Hubhus directly to Pipedrive — create or update deals, activities, and owner assignments automatically. Pipedrive IDs are written back to the Hubhus lead via JSON map, enabling both first-time booking flows and rebooking updates.
TL;DR
Add your Pipedrive API token as an External API key in Hubhus and reference it as {**api_key_pipedrive-token**} in the x-api-token header on every request. Create five HTTP request templates: Find owner (GET), Create deal (POST), Create activity (POST), Update activity (PATCH), Update deal (PATCH). Use JSON map to write pipedrive-deal-id and pipedrive-activity-id back to the lead. Send dates as UTC using <hh-date.format>. Never wrap numeric IDs in quotes in the JSON body.
Get started in 5 steps
Store the Pipedrive API token
Go to Account → Integrations & API → External API keys and add your Pipedrive API token with the slug pipedrive-token. On every HTTP request template, add the header x-api-token: {**api_key_pipedrive-token**}. Add Content-Type: application/json on POST and PATCH requests.
Create Hubhus data fields
Create these data fields on the lead in Hubhus: pipedrive-owner-id, pipedrive-owner-name, pipedrive-owner-email, pipedrive-deal-id, pipedrive-activity-id. Hubhus uses hyphens in slugs — placeholders are written as {{pipedrive-deal-id}}, not with underscores.
Create "Find owner" template (GET)
GET https://{companydomain}.pipedrive.com/api/v1/users/find?term=%event_user_email%&search_by_email=1. JSON map: {{pipedrive-owner-id}}=data.0.id, {{pipedrive-owner-name}}=data.0.name. Only run this if pipedrive-owner-id is empty.
Create "Create deal" and "Create activity" templates (POST)
Create deal: POST to /api/v2/deals with owner_id, pipeline_id, stage_id as plain numbers (no quotes). JSON map: {{pipedrive-deal-id}}=data.id. Create activity: POST to /api/v2/activities with deal_id, due_date, due_time, and duration. JSON map: {{pipedrive-activity-id}}=data.id. Only run if the respective ID field is empty.
Create "Update activity" and "Update deal" templates (PATCH)
PATCH to /api/v2/activities/{{pipedrive-activity-id}} and /api/v2/deals/{{pipedrive-deal-id}}. Only run if the respective ID already exists on the lead. These handle rebooking and ownership changes without creating duplicates.
x-api-token: {**api_key_pipedrive-token**} ·
Numeric IDs: never wrap in quotes ·
Dates: send as UTC with hh-date.format
Read more⌄
Request 1 — Find Pipedrive owner
Method: GET
https://{companydomain}.pipedrive.com/api/v1/users/find?term=%event_user_email%&search_by_email=1
Headers:
x-api-token: {**api_key_pipedrive-token**}
JSON map:
{{pipedrive-owner-id}}=data.0.id
{{pipedrive-owner-name}}=data.0.name
{{pipedrive-owner-email}}=data.0.email
If the employee's email doesn't match an active Pipedrive user, data.0.id will be empty. Subsequent requests using owner_id will fail if this value is missing — add a condition to only run the deal/activity requests when pipedrive-owner-id is set.
Request 2 — Create deal
Method: POST URL: https://{companydomain}.pipedrive.com/api/v2/deals
{
"title": "%lead_name%",
"owner_id": {{pipedrive-owner-id}},
"pipeline_id": PIPELINE_ID,
"stage_id": STAGE_ID,
"status": "open"
}
JSON map: {{pipedrive-deal-id}}=data.id
Important: owner_id, pipeline_id, and stage_id must be plain numbers — not wrapped in quotes. "owner_id": {{pipedrive-owner-id}} is correct. "owner_id": "{{pipedrive-owner-id}}" will cause an API error.
Request 3 — Create activity
Method: POST URL: https://{companydomain}.pipedrive.com/api/v2/activities
{
"subject": "Besøg - %lead_name%",
"type": "meeting",
"owner_id": {{pipedrive-owner-id}},
"deal_id": {{pipedrive-deal-id}},
"due_date": "<hh-date.format input='%event_start_datetime_db%' output='Y-m-d' timezone='UTC' />",
"due_time": "<hh-date.format input='%event_start_datetime_db%' output='H:i' timezone='UTC' />",
"duration": "<hh-date.format input='1970-01-01 00:00:00 +%event_duration_minutes% minutes' output='H:i' />",
"busy": true,
"done": false,
"note": "Besøg booket via Hubhus.\n\nNavn: %lead_name%\nTelefon: %lead_phone%\nEmail: %lead_email%\nAdresse: %lead_full_address%\nHubhus lead ID: %lead_id%"
}
JSON map: {{pipedrive-activity-id}}=data.id
Use single quotes inside the hh-date.format tags so the JSON string remains valid. Duration example: if %event_duration_minutes% = 60, the output is 01:00.
Request 4 — Update activity
Method: PATCH URL: https://{companydomain}.pipedrive.com/api/v2/activities/{{pipedrive-activity-id}}
Same body structure as Create activity. Use the same hh-date.format fields for due_date, due_time, and duration. JSON map: {{pipedrive-activity-id}}=data.id. Only run if pipedrive-activity-id already exists on the lead.
Request 5 — Update deal
Method: PATCH URL: https://{companydomain}.pipedrive.com/api/v2/deals/{{pipedrive-deal-id}}
{
"owner_id": {{pipedrive-owner-id}},
"pipeline_id": PIPELINE_ID,
"stage_id": STAGE_ID,
"status": "open"
}
Date, time, and timezone
Pipedrive activity API uses due_date, due_time, and duration. Send due_date and due_time as UTC — Pipedrive UI converts to local timezone for display.
| Field | Format | Example output |
|---|---|---|
due_date | output='Y-m-d' timezone='UTC' | 2026-06-15 |
due_time | output='H:i' timezone='UTC' | 04:00 (= 06:00 CEST) |
duration | input='1970-01-01 00:00:00 +%event_duration_minutes% minutes' | 01:00 (for 60 min) |
Flow logic and duplicate protection
First booking (no IDs on lead yet):
- Find owner — run if
pipedrive-owner-idis empty - Create deal — run if
pipedrive-deal-idis empty AND owner ID is set - Create activity — run if
pipedrive-activity-idis empty AND deal ID and owner ID are set
Rebooking (IDs already exist):
- Find/update owner if employee changed
- Update deal if owner or stage needs updating
- Update activity — run only if
pipedrive-activity-idexists - Create activity as fallback — run if
pipedrive-deal-idexists butpipedrive-activity-idis empty
If the same action listener triggers multiple requests in sequence, ensure that the JSON map from each request is saved before the next request reads the value.
Troubleshooting
Invalid JSON / empty numeric fields
If owner_id or deal_id is empty, the JSON body becomes invalid ("owner_id": ,). Ensure the ID fields are populated before the request runs. Use conditions to skip requests when required IDs are missing.
Wrong time displayed in Pipedrive UI
Send due_date and due_time as UTC (timezone='UTC'). Pipedrive converts to local time for display. Sending local time directly will show the wrong time in Pipedrive.
URL contains HTTP method
The URL field must not include the method. Set the method separately in Hubhus. Correct: Method = GET, URL = https://example.pipedrive.com/api/v1/users/find.
hh-date.format breaks JSON
Use single quotes inside the tag attributes so the JSON string remains valid: "due_time": "<hh-date.format input='%event_start_datetime_db%' output='H:i' timezone='UTC' />". Using double quotes inside the tag will break the JSON structure.
Common searches
Pipedrive • deal • activity • owner • CRM • integration • pipeline • stage • HTTP request • x-api-token • pipedrive-deal-id
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article