Pipedrive integration

Modified on Thu, 11 Jun at 2:38 PM

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

1

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.

2

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.

3

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.

4

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.

5

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.

Auth header: 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_dateoutput='Y-m-d' timezone='UTC'2026-06-15
due_timeoutput='H:i' timezone='UTC'04:00 (= 06:00 CEST)
durationinput='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):

  1. Find owner — run if pipedrive-owner-id is empty
  2. Create deal — run if pipedrive-deal-id is empty AND owner ID is set
  3. Create activity — run if pipedrive-activity-id is empty AND deal ID and owner ID are set

Rebooking (IDs already exist):

  1. Find/update owner if employee changed
  2. Update deal if owner or stage needs updating
  3. Update activity — run only if pipedrive-activity-id exists
  4. Create activity as fallback — run if pipedrive-deal-id exists but pipedrive-activity-id is 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

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article