Pipedrive API v2 migration guide

Migration Guide

This document outlines the differences between Pipedrive API v1 and v2 of endpoints which are available on v2. Where available, please use API v2 for the best performance and developer experience.

General API Changes

  • All v2 endpoints now have significantly stricter input validation to improve data quality and prevent ambiguity.
    • Any boolean value fields which returned or accepted 1 or 0 now only return and accept true and false respectively.
    • Numeric fields no longer coerce string input to number and instead throw a validation error.
  • Related objects have been removed from API responses to prevent too eager fetching of unnecessary data. Use subsequent API calls to fetch them if you still need them.
  • All timestamps in the v2 API are now in RFC 3339 format (e.g. 2024-01-01T00:00:00Z) unless specified otherwise to ensure clarity regarding timezones.
  • Support for field selectors has been removed.
  • V1 endpoints, which were using HTTP PUT method have been switched to use HTTP PATCH method in v2 for compliance with REST best practices.
  • Only /api/v2/... prefix is supported. Previously both /api/v1/... and /v1/... could be used.

Custom Fields

Entity custom fields have been moved to a separate custom_fields object with clearer syntax.

Previously custom fields were on the root level of the entity object and had separate keys for their subfields. For example, a currency custom field in API v1 was presented as

"d4de1c1518b4531717c676029a45911c340390a6": 2300,
"d4de1c1518b4531717c676029a45911c340390a6_currency": "EUR"

The same field is now presented in API v2 as

"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": {
  "value": 2300,
  "currency": "EUR"
},
...
}

See subsections below for the exact changes for each custom field type.

Text, Large Text and Autocomplete Custom Fields Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": "my text value"
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": "my text value",
  ...
}

Numeric Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": 500
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": 500,
  ...
}

Currency Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": 500,
"d4de1c1518b4531717c676029a45911c340390a6_currency": "USD"
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": {
  "value": 500,
  "currency": "USD"
},
...
}

Address Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": "530 Fifth Avenue, New York, NY, USA",
"d4de1c1518b4531717c676029a45911c340390a6_route": "5th Avenue",
"d4de1c1518b4531717c676029a45911c340390a6_subpremise": null, // no longer included, was always null
"d4de1c1518b4531717c676029a45911c340390a6_country": "United States",
"d4de1c1518b4531717c676029a45911c340390a6_locality": "New York",
"d4de1c1518b4531717c676029a45911c340390a6_postal_code": "10036",
"d4de1c1518b4531717c676029a45911c340390a6_sublocality": "Manhattan",
"d4de1c1518b4531717c676029a45911c340390a6_street_number": "530",
"d4de1c1518b4531717c676029a45911c340390a6_admin_area_level_1": "New York",
"d4de1c1518b4531717c676029a45911c340390a6_admin_area_level_2": "New York County"
"d4de1c1518b4531717c676029a45911c340390a6_formatted_address": "530 5th Ave, New York, NY 10036, USA",
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": {
  "route": "5th Avenue",
  "value": "530 Fifth Avenue, New York, NY, USA",
  "country": "United States",
  "locality": "New York",
  "postal_code": "10036",
  "sublocality": "Manhattan",
  "street_number": "530",
  "admin_area_level_1": "New York",
  "admin_area_level_2": "New York County",
  "formatted_address": "530 5th Ave, New York, NY 10036, USA"
},
...
}

Single Option Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": "123" // ID of the selected option. Can be mapped to user presented value via field endpoints.
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": 123, // option ID is now a number
  ...
}

Multiple Option Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": "123,456" // concatenated IDs of the selected option. Can be mapped to user presented value via field endpoints.
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": [123, 456], // option IDs are now in an array as numeric values.
...
}

User, Person, Organization Custom Fields Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": 1234 // ID of the user/person/org
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": 1234, // ID of the user/person/org
  ...
}

Date Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": "2024-01-01"
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": "2024-01-01",
  ...
}

Date Range Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": "2024-01-01"
"d4de1c1518b4531717c676029a45911c340390a6_until": "2024-02-01"
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": {
  "value": "2024-01-01",
  "until": "2024-02-01"
},
...
}

Time Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": "09:00:00"
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": "09:00:00",
  ...
}

Time Range Custom Field Format Changes

API v1
"d4de1c1518b4531717c676029a45911c340390a6": "09:00:00"
"d4de1c1518b4531717c676029a45911c340390a6_until": "11:00:00"
API v2
"custom_fields": {
  ...,
  "d4de1c1518b4531717c676029a45911c340390a6": {
  "value": "09:00:00",
  "until": "11:00:00"
},
...
}

Pagination

Offset based pagination (start & limit) has been replaced with cursor based pagination (cursor & limit), which makes iterating over large collections significantly faster. See Pagination for more information.

Sorting

Endpoints, which support sorting, now have 2 optional parameters (sort_by and sort_direction) instead of 1 (sort).
- sort_by accepted values: id, add_time, update_time plus a few additional fields depending on the entity. Defaults to id.
- sort_direction accepted values: asc, desc. Defaults to asc.

A maximum of 1 field to sort by can be provided.

Products API

Products Object

Changes Summary

Please note that this section does not include the changes already covered in General API Changes section.

  • first_char and files_count fields are no longer included
  • visible_to field type has changed from string to integer. Old possible values were "1", "3", "5", "7". New possible values are 1, 3, 5, 7.
  • selectable field has been renamed to is_linkable for clarity. When set to true, the product is linkable to deals.
  • active_flag field has been replaced with is_deleted. It is the negation of the old value. When an entity has is_deleted set to true, the entity is considered soft deleted and will be fully deleted after 30 days of last activity.
  • product_variations has been removed to a separate Product Variations API described below.

Old v1 Product Object Example

{
    "id": 3,
    "name": "Name",
    "code": "Code",
    "description": "Description",
    "unit": "Unit",
    "tax": 20,
    "category": "262",
    "active_flag": true, // replaced with is_deleted flag. NB: is_deleted is the negated value of the old active_flag.
    "selectable": true, // replaced with is_linkable flag
    "first_char": "n", // no longer included
    "visible_to": "7", // is now an integer
    "owner_id": { // Replaced with only the numeric id of the owner user
        "id": 6192726,
        "name": "Owner Name",
        "email": "[email protected]",
        "has_pic": 1,
        "pic_hash": "08bcf87d30a6662032680b65bfa1b509",
        "active_flag": true,
        "value": 6192726
    },
    "files_count": null, // no longer included
    "add_time": "2021-01-11 17:30:10",
    "update_time": "2024-01-09 09:31:15",
    "prices": [
        {
            "id": 5, // no longer included
            "product_id": 3,
            "price": 54,
            "currency": "EUR",
            "cost": 0,
            "overhead_cost": 0,
            "price_formatted": "54 €" // no longer included
        }
    ],
    "product_variations": [], // moved to a separate product variations API
    "53c2f18db6a1655d6af8bba77d9679565f975fd8": "Text Custom Field", // wrapped in custom_fields object
    "d4de1c1518b4531717c676029a45911c340390a6": 2300, // wrapped in custom_fields object
    "d4de1c1518b4531717c676029a45911c340390a6_currency": "EUR" // wrapped in custom_fields object
}

New v2 Product Object Example

{
    "id": 3,
    "name": "Name",
    "tax": 20,
    "add_time": "2021-01-11T17:30:10Z",
    "update_time": "2024-01-09T09:31:15Z",
    "description": "Description",
    "code": "Code",
    "unit": "Unit",
    "owner_id": 6192726, // is no longer a user object, just the id
    "category": "262",
    "visible_to": 7, // is now an integer
    "is_deleted": false, // Replaces old 'active_flag' field. NB: is_deleted is the negated value of the old active_flag.
    "is_linkable": true, // Replaces old 'selectable' field
    "prices": [
        {
            "product_id": 3,
            "price": 54,
            "currency": "EUR",
            "cost": 0,
            "direct_cost": 0
        }
    ],
    "custom_fields": { // custom fields are no longer flat root level fields
        "53c2f18db6a1655d6af8bba77d9679565f975fd8": "Text Custom Field",
        "d4de1c1518b4531717c676029a45911c340390a6": {
            "value": 2300,
            "currency": "EUR"
        }
    }
}

GET /api/v1/products/:id to GET /api/v2/products/:id

Please note that this section does not include the changes already covered in General API Changes section.

Returned product object has changed, see Products Object for details.

GET /api/v1/products to GET /api/v2/products

Please note that this section does not include the changes already covered in General API Changes section.

Returned product object has changed, see Products Object for details.

  • sorting is only supported by id, add_time, update_time or name
  • optional parameter user_id has been renamed to owner_id. It allows filtering products by specific owner user.
  • get_summary and first_char parameters have been removed

POST /api/v1/products to POST /api/v2/products

Please note that this section does not include the changes already covered in General API Changes section.

Only the name field is required. Everything else is optional and expected in the format described in Products Object section.

  • It is no longer possible to create an already deleted entity with POST.

PUT /api/v1/products to PATCH /api/v2/products

Please note that this section does not include the changes already covered in General API Changes section.

Any fields changed are expected to be in the format described in Products Object section.

  • It is no longer possible to use PATCH (former PUT) requests to delete an entity. Use corresponding DELETE endpoint instead.
  • When updating prices, the whole existing array will be replaced with the passed array.

DELETE /api/v1/products to DELETE /api/v2/products

No changes other than version change in the URL.

Deal Products API

Deal Products Object

Changes Summary

Please note that this section does not include the changes already covered in General API Changes section.

  • product, order_nr, quantity_formatted and sum_formatted fields are no longer included.
  • active_flag has been removed as it was always true.
  • comments field can not be null anymore. If it is not set, it will be an empty string "".

Old v1 Deal Product Object Example

{
    "id": 1,
    "deal_id": 1,
    "product_id": 1,
    "product_variation_id": null,
    "name": "Name",
    "order_nr": 1, // no longer included
    "item_price": 10,
    "quantity": 3,
    "duration": 1,
    "duration_unit": null,
    "sum": 30,
    "tax": 0,
    "tax_method": "inclusive",
    "currency": "EUR",
    "active_flag": true, // removed, was always true
    "enabled_flag": true, // renamed to is_enabled
    "add_time": "2020-11-12 12:10:45",
    "last_edit": "2022-11-12 12:10:45", // renamed to update_time
    "comments": null, // can not be null anymore. If not set, is an empty string instead.
    "quantity_formatted": "3", // no longer included
    "sum_formatted": "30 €", // no longer included
    "discount": 0,
    "discount_type": "percentage",
    "product": null // no longer included
}

New v2 Deal Product Object Example

{
    "id": 1,
    "deal_id": 1,
    "product_id": 1,
    "product_variation_id": null,
    "name": "Name",
    "item_price": 10,
    "quantity": 3,
    "sum": 30,
    "tax": 0,
    "tax_method": "inclusive",
    "currency": "EUR",
    "is_enabled": true, // renamed from enabled_flag
    "add_time": "2020-11-12T12:10:45Z",
    "update_time": "2022-11-12T12:10:45Z", // renamed from last_edit
    "comments": "", // can not be null anymore
    "discount": 0,
    "discount_type": "percentage"
}

GET /api/v1/deals/:id/products to GET /api/v2/deals/:id/products or GET /api/v2/deals/products?deal_ids=..,..

Please note that this section does not include the changes already covered in General API Changes section.

Returned product object has changed, see Deal Products Object for details.

  • New alternative endpoint is available to fetch multiple deals' products at once: GET /api/v2/deals/products. You can fetch up to 100 deals products at once by providing a comma separated list of deal IDs in deal_ids querystring parameter.

POST /api/v1/deals/:id/products to POST /api/v2/deals/:id/products

Please note that this section does not include the changes already covered in General API Changes section.

Keys are expected in the format described in Deal Products Object section.

  • It is no longer possible to create an already deleted entity with POST.

PUT /api/v1/deals/:id/products to PATCH /api/v2/deals/:id/products

Any fields changed are expected to be in the format described in Deal Products Object section.

  • It is no longer possible to use PATCH (former PUT) requests to delete an entity. Use the corresponding DELETE endpoint instead.

DELETE /api/v1/deals/:id/products to DELETE /api/v2/deals/:id/products

No changes other than version change in the URL.

Product Variations API

Product Variation Object

Changes Summary

Please note that this section does not include the changes already covered in General API Changes section.

Previously product variations were returned as part of the main products API. They have now been moved to a separate API with the following endpoints:

  • GET /v2/products/:id/variations
  • POST /v2/products/:id/variations
  • PATCH /v2/products/:id/variations/:id
  • DELETE /v2/products/:id/variations/:id

The prices object no longer includes the following fields: id, product_id, comment and price_formatted.

Old v1 Product Variation Object Example (within old v1/products API)

{
    "id": 1,
    "name": "Variation 1",
    "product_id": 1,
    "prices": [
        {
            "id": 1, // no longer included
            "product_id": 1, // no longer included within price object, use root level field instead
            "product_variation_id": 1,
            "price": 10,
            "currency": "EUR",
            "cost": 20,
            "comment": "", // no longer included
            "price_formatted": "10 €" // no longer included
        }
    ]
}

New v2 Product Variation Object Example

{
    "id": 1,
    "name": "Variation 1",
    "product_id": 1,
    "prices": [
        {
            "product_variation_id": 1,
            "price": 10,
            "currency": "EUR",
            "cost": 20
        }
    ]
}

Search API

GET /api/v1/deals/search to GET /api/v2/deals/search

GET /api/v1/persons/search to GET /api/v2/persons/search

GET /api/v1/organizations/search to GET /api/v2/organizations/search

GET /api/v1/leads/search to GET /api/v2/leads/search

GET /api/v1/products/search to GET /api/v2/products/search

GET /api/v1/itemSearch to GET /api/v2/itemSearch

Only change is a switch to cursor based pagination (cursor and limit instead of start and limit). See Pagination for more information.

GET /api/v1/itemSearch/field to GET /api/v2/itemSearch/field

  • The endpoint now uses cursor based pagination. See Pagination for more information.
  • field_key parameter has been renamed to field.
  • field_type parameter has been renamed to entity_type.
  • entity_type accepted values have been simplified to just deal, lead , person, organization, product, project from previous dealField, leadField etc.
  • return_item_ids parameter has been removed, the response always includes item ids now.
  • exact_match boolean parameter has been replaced with a string match parameter. Accepted values are
    • exact - fastest. Matches only if the field value is exactly the same as the term.
    • beginning - fast. Matches fields by beginning, e.g. finds my field value with my fie
    • middle - slowest. Old default behaviour. Matches fields by any substring, e.g. finds my field value with ld va. We recommend using other types of matching where possible for best experience.

Pipelines API

Pipeline Object

Changes Summary

Please note that this section does not include the changes already covered in General API Changes section.

  • url_title field is no longer included.
  • selected field has been renamed to is_selected for clarity. When set to true, the product is linkable to deals.
  • active_flag field has been replaced with is_deleted. It is the negation of the old value. When an entity has is_deleted set to true, the entity is considered soft deleted and will be fully deleted after 30 days of last activity.
  • order_nr is now read-only. When creating a new pipeline, it is placed at the end of existing Pipelines list. If user wants, they can reorder pipelines in the UI.

Old v1 Pipeline Object Example

{
    "id": 1,
    "name": "Sales Pipeline",
    "url_title": "Sales-Pipeline", //  removed
    "order_nr": 1,
    "active": true, // replaced with is_deleted. NB: Negation of the old value.
    "deal_probability": false, // replaced with is_deal_probability_enabled
    "add_time": "2018-09-03 17:05:08", 
    "update_time": "2018-09-04 12:46:03",
    "selected": true // renamed to is_selected
}

New v2 Pipeline Object Example

{
    "id": 1,
    "name": "Sales Pipeline",
    "order_nr": 1,
    "is_deleted": false, // replaces "active". NB: Negation of the old value.
    "is_deal_probability_enabled": false, // replaces "deal_probability"
    "add_time": "2018-09-03T17:05:08Z",
    "update_time": "2018-09-04T12:46:03Z",
    "is_selected": true // renamed from "selected"
}

GET /api/v1/pipelines/:id to GET /api/v2/pipelines/:id

Please note that this section does not include the changes already covered in General API Changes section.

Returned pipeline object has changed, see Pipeline Object for details.

GET /api/v1/pipelines to GET /api/v2/pipelines

Please note that this section does not include the changes already covered in General API Changes section.

Returned pipeline object has changed, see Pipeline Object for details.

POST /api/v1/pipelines to POST /api/v2/pipelines

Please note that this section does not include the changes already covered in General API Changes section.

Only the name field is required. Everything else is optional and expected in the format described in Pipeline Object section.

  • It is no longer possible to create an already deleted entity with POST.

PUT /api/v1/pipelines to PATCH /api/v2/pipelines

Please note that this section does not include the changes already covered in General API Changes section.

Any fields changed are expected to be in the format described in Pipeline Object section.

  • It is no longer possible to use PATCH (former PUT) requests to delete an entity. Use corresponding DELETE endpoint instead.

DELETE /api/v1/pipelines to DELETE /api/v2/pipelines

No changes other than version change in the URL.

Stages API

Stage Object

Changes Summary

Please note that this section does not include the changes already covered in General API Changes section.

  • pipeline_name and pipeline_deal_probability fields have been removed. Query the pipeline object if you need these.
  • rotten_flag has been replaced with is_deal_rot_enabled flag.
  • rotten_days has been replaced with days_to_rotten for clarity.
  • active_flag field has been replaced with is_deleted. It is the negation of the old value.

Old v1 Stage Object Example

{
    "id": 1,
    "order_nr": 1,
    "name": "Lead In",
    "active_flag": true, // replaced with is_deleted. NB: Negation of the old value.
    "deal_probability": 100,
    "pipeline_id": 1,
    "pipeline_name": "Sales Pipeline", // removed, query pipeline API instead
    "pipeline_deal_probability": false, // removed, query pipeline API instead
    "rotten_flag": false, // replaced with is_deal_rot_enabled
    "rotten_days": null, // replaced with days_to_rotten
    "add_time": "2018-09-04 06:24:59",
    "update_time": null
} 

New v2 Stage Object Example

{
    "id": 1,
    "order_nr": 1,
    "name": "Lead In",
    "is_deleted": false, // replaces "active_flag". NB: Negation of the old value.
    "deal_probability": 100,
    "pipeline_id": 1,
    "is_deal_rot_enabled": false, // replaces "rotten_flag"
    "days_to_rotten": null, // replaces "rotten_days"
    "add_time": "2018-09-04T06:24:59Z",
    "update_time": null
}

GET /api/v1/stages/:id to GET /api/v2/stages/:id

Please note that this section does not include the changes already covered in General API Changes section.

Returned stage object has changed, see Stage Object for details.

GET /api/v1/stages to GET /api/v2/stages

Please note that this section does not include the changes already covered in General API Changes section.

Returned stage object has changed, see Stage Object for details.

POST /api/v1/stages to POST /api/v2/stages

Please note that this section does not include the changes already covered in General API Changes section.

Only the name field is required. Everything else is optional and expected in the format described in Stage Object section.

  • It is no longer possible to create an already deleted entity with POST.

PUT /api/v1/stages to PATCH /api/v2/stages

Please note that this section does not include the changes already covered in General API Changes section.

Any fields changed are expected to be in the format described in Stage Object section.

  • It is no longer possible to use PATCH (former PUT) requests to delete an entity. Use corresponding DELETE endpoint instead.

DELETE /api/v1/stages to DELETE /api/v2/stages

No changes other than version change in the URL.