The v1 Contact Lists API will be sunset on September 30, 2025. After this date, calls made to the v1 endpoints will no longer function. If you’re using any of the affected endpoints, you’ll need to update your calls to use the corresponding newer endpoints. Review this guide to understand which endpoints are being sunset and to which endpoints you should migrate based on your goal. For complete guidance about using the v3 list endpoints, refer to the v3 lists API guide.

Contact list ID migration

Contact lists have two list IDs:
  • legacyListId: the ID used by the v1 lists API.
  • listId: the ID used by the v3 lists API.
As a part of migrating to the v3 API, you’ll need to update your system to use the listId values instead of legacyListId. For any given list, the value in each field will be different. However, it’s possible that one list’s legacyListId value matches another list’s listId value, so ensure you retrieve all list IDs and compare them carefully to prevent list mapping issues. To retrieve the legacyListId and listId values of each list:
  1. Use the ID mapping endpoint to get the v3 list IDs for all of the lists in your account.
  2. To prevent data loss in the event of a mistake during migration, store the v3 list IDs alongside the v1 list IDs.
  3. Once all v3 List IDs have been fetched and stored, migrate to using the v3 List APIs with the v3 list IDs.
  4. When you’ve fully switched over to using the v3 lists API, you can remove the stored v1 list IDs and drop any references to v1 list ID information.

Use the list ID mapping endpoint

To fetch mappings one at a time, make a GET request to /crm/v3/lists/idmapping?legacyListId={legacyListId} with the v1 list ID in the legacyListID parameter. Your response will look like:
{
  "listId": "61",
  "legacyListId": "64"
}
To fetch multiple ID mappings in one batch, make a POST request to /crm/v3/lists/idmapping and include the legacyListID values within an array, limited to 10,000 entries. For example, your request would look like:
["64", "33", "22566"]
The response would look like:
{
  "missingLegacyListIds": ["22566"],
  "legacyListIdsToIdsMapping": [
    {
      "listId": "61",
      "legacyListId": "64"
    },
    {
      "listId": "38",
      "legacyListId": "33"
    }
  ]
}
You can now use the listId values to refer to lists in the v3 endpoints. The v3 API is the source of truth, so if a mapping does not exist via the v3 API (indicated by the missingLegacyListIds field), it means the list no longer exists.

Impacted endpoints

The following endpoints will return a 404 error starting on September 30, 2025. Create, update, and delete contact list endpoints: Retrieve contact list endpoints: Retrieve contacts in a list endpoints: Retrieve contacts with list memberships endpoints: The following endpoints will continue to function, but starting on September 30, 2025, will no longer return list memberships:
  • Get a contact by visitor ID: GET /contacts/v1/contact/vid/{vid}/profile
  • Get a batch of contacts by visitor ID: GET /contacts/v1/contact/vids/batch
  • Get a contact by email address: GET /contacts/v1/contact/email/{contact_email}/profile
  • Get a batch of contacts by email address: GET /contacts/v1/contact/emails/batch
  • Get a contact by user token: GET /contacts/v1/contact/utk/{contact_utk}/profile
  • Get a batch of contacts by user token: GET /contacts/v1/contact/byUtk/batch

Migrate from v1 to v3 endpoints

If you were previously using any of the v1 list endpoints, you can migrate to the equivalent endpoints, detailed in the sections below.
in the v3 endpoint request URLs and request bodies, you must use the v3 list ID (listId). Using a v1 list ID (legacyListId) for these endpoints may result in updating or deleting the wrong list. Learn more about list ID migration.

Create lists

If you’re using POST /contacts/v1/lists to create lists, migrate to POST /crm/v3/lists. In the request body, you must include the following fields: name, objectTypeId, and processingType. Refer to the v3 lists API guide for more information on other fields. You can create lists for objects other than contacts with the v3 API, but if your goal is to create a list of contacts, your objectTypeId value must be 0-1. For example:
{
  "name": "My static list",
  "objectTypeId": "0-1",
  "processingType": "MANUAL"
}
When you create a list with the v3 endpoint, the listId is returned, which should be the list ID used moving forward.

Update lists

If you’re using POST /contacts/v1/lists/{legacyListId} to update a list, migrate to the following v3 endpoints depending on your goal. To update an active list’s filters, migrate to PUT /crm/v3/lists/{listId}/update-list-filters. In your request, include the filterBranch parameter to your request. Learn more about setting up filter branches. To update a list’s name, migrate to PUT /crm/v3/lists/{listId}/update-list-name. In your request URL, include the v3 listId of the list and the updated listName. For example: crm/v3/lists/12345/update-list-name?listName=New%20list%20name.

Add or remove records in a list

If you’re updating contact list membership using POST /contacts/v1/lists/{legacyListId}/add and POST /contacts/v1/lists/{legacyListId}/remove, migrate to the following endpoints depending on your goal. You can only manually add or remove records in a static list.
  • To add records to a list, migrate to PUT /crm/v3/lists/{listId}/memberships/add. Include an array with the id values of records to add.
  • To remove records from a list, migrate to PUT /crm/v3/lists/{listId}/memberships/remove. Include an array with the id values of records to remove.
["1234", "5678", "9101"]
To both add and remove records from a list, migrate to PUT /crm/v3/lists/{listId}/memberships/add-and-remove. Include the recordsToRemove array with id values of records to remove from the list and the recordsToAdd array with id values of records to add to the list.
{
  "recordIdsToRemove": [654, "321"],
  "recordIdsToAdd": [123, 456, 789]
}

Delete lists

If you’re using DELETE /contacts/v1/lists/{legacyListId} to delete a list, migrate to DELETE /crm/v3/lists/{listId}.

Get all static lists

If you’re using GET /contacts/v1/lists/static to get static lists, migrate to POST /crm/v3/lists/search. In the request body, include SNAPSHOT and MANUAL in the processingTypes array. Include an additionalProperties array to request that certain list properties are returned.
{
  "offset": 0,
  "count": 100,
  "processingTypes": ["MANUAL", "SNAPSHOT"]
}

Get all active lists

If you’re using GET /contacts/v1/lists/dynamic to get active lists, migrate to POST /crm/v3/lists/search. In the request body, include DYNAMIC in the processingTypes array. Include an additionalProperties array to request that certain list properties are returned.
{
  "offset": 0,
  "count": 100,
  "processingTypes": ["DYNAMIC"]
}

Get lists by list ID

If you’re using GET /contacts/v1/lists/{legacyListId} to retrieve individual lists by ID, migrate to GET /crm/v3/lists/{listId}. If you’re using GET /contacts/v1/lists/batch to retrieve multiple lists by ID, migrate to GET /crm/v3/lists. In the request URL, include listId values. To include filter branches in the response, set the includeListFilters query param to true. For example, your request URL would look like: /crm/v3/lists?includeFilters=true&listIds=42&listIds=51. You can also use the search API to filter the lists further, such as by processingType or custom list properties.

Get all members of a list

If you’re using GET /contacts/v1/lists/{legacyListId}/contacts/all to retrieve contacts in a list, migrate to GET /crm/v3/lists/{listId}/memberships. Records will be returned in order based on their id values. Your response will look similar to the following:
{
  "results": [
    {
      "recordId": "13161075754",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "13242183272",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "14559658632",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "20903185697",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "20903217801",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "20903639452",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "20903662261",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "20903719953",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "20903752823",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    },
    {
      "recordId": "20903842625",
      "membershipTimestamp": "2025-05-22T16:33:17.864Z"
    }
  ],
  "total": 10
}

Get recent list members

If you’re using GET /contacts/v1/lists/{legacyListId}/contacts/recent to retrieve contacts recently added to a list, migrate to GET /crm/v3/lists/{listId}/memberships/join-order. Records will be returned with their id values in the order in which they were added to the list. Your response will look similar to the following:
{
  "results": [
    {
      "recordId": "41720992115",
      "membershipTimestamp": "2025-07-28T13:42:08.595Z"
    },
    {
      "recordId": "79129291921",
      "membershipTimestamp": "2025-01-21T18:06:02.387Z"
    },
    {
      "recordId": "33451",
      "membershipTimestamp": "2023-08-31T16:24:37.296Z"
    }
  ],
  "total": 2
}

Retrieve records with list memberships

If you’re using GET /contacts/v1/lists/all/contacts/all, GET /contacts/v1/lists/recently_updated/contacts/recent, or GET /contacts/v1/lists/all/contacts/recent to retrieve contacts with list memberships, you’ll need to migrate to the v3 object and search endpoints. This is because migration for retrieving contacts and their memberships requires two calls: one to retrieve the records, then another to retrieve their list memberships. First, make a POST request to /crm/v3/objects/{objectTypeId}/search with the object for which you want to search records (i.e. 0-1 for contacts). You can add filters to specify the records you want.
  • To retrieve recently created records, filter by createdate.
  • To retrieve recently updated records, filter by lastmodifieddate.
You can add properties to retrieve more details about the records as needed. For example, to search for contacts edited after May 31, 2025:
{
  "properties": [
    "firstname",
    "lastname",
    "email",
    "hs_object_id",
    "createdate",
    "lastmodifieddate"
  ],
  "filterGroups": [
    {
      "filters": [
        {
          "propertyName": "lastmodifieddate",
          "operator": "GT",
          "value": "2025-05-31"
        }
      ]
    }
  ]
}
Next, use the object endpoint to retrieve the membership details for the contacts. From your search request, use a record’s id value to retrieve its list membership details. Make a GET request to /crm/v3/lists/records/{objectTypeId}/{recordId}/memberships. For example, to retrieve a contact’s memberships, your request URL would look like /crm/v3/lists/records/0-1/1234567/memberships. Your response will look like:
{
  "results": [
    {
      "listId": "76",
      "listVersion": 1,
      "isPublicList": true,
      "firstAddedTimestamp": "2025-07-28T13:42:08.595Z",
      "lastAddedTimestamp": "2025-07-28T13:42:08.595Z"
    },
    {
      "listId": "78",
      "listVersion": 1,
      "isPublicList": true,
      "firstAddedTimestamp": "2025-07-28T13:42:08.595Z",
      "lastAddedTimestamp": "2025-07-28T13:42:08.595Z"
    },
    {
      "listId": "493",
      "listVersion": 1,
      "isPublicList": false,
      "firstAddedTimestamp": "2024-07-23T19:40:36.192Z",
      "lastAddedTimestamp": "2024-07-23T19:40:36.192Z"
    },
    {
      "listId": "541",
      "listVersion": 1,
      "isPublicList": true,
      "firstAddedTimestamp": "2025-04-21T14:01:43.475Z",
      "lastAddedTimestamp": "2025-04-21T14:01:43.475Z"
    },
    {
      "listId": "492",
      "listVersion": 1,
      "isPublicList": false,
      "firstAddedTimestamp": "2024-07-23T19:36:11.890Z",
      "lastAddedTimestamp": "2024-07-23T19:36:11.890Z"
    }
  ]
}