Skip to content

The moment it happens

Remove a list of contacts from HubSpot

Send a list of email addresses and those contacts are archived, with a count of how many were removed.

Runs
The moment it happens
Apps
HubSpot
AI
Not needed
Access
crm.objects.contacts.write

Send this to your assistant

Create a ClickRuntime automation: give me a link I can send a CSV of email addresses to. Delete those contacts in HubSpot and email me how many were removed.

Paste it into your assistant. It tells you what it will send or change before it runs live.

First time? Adding ClickRuntime to your assistant takes about two minutes.

Why use it

Why teams use this automation

Cleaning a HubSpot database is a job nobody wants. After a GDPR erasure batch, a bounced-email sweep, a list of competitors that signed up for a webinar or a trade-show import that went wrong, someone has a spreadsheet of 800 email addresses to remove. Searching for each one in the UI and clicking delete takes the better part of a day, and a mis-click removes the wrong person. Meanwhile, contacts who asked to be removed continue to get emails.

You send a list of email addresses to a private link. They are parsed, each is looked up to find its contact ID, the contacts are archived in batches, and you get an email with the number removed and any addresses that were not found.

It suits marketing operations, privacy officers and anyone who handles removal lists in bulk.

What you get out of it

  • Erasure requests are met on time

    Privacy rules give you a limited period to act on a deletion request. A batch process helps you meet that window without a day of manual clicking. Meeting the deadline protects the company, and it also shows contacts their request is taken seriously.

  • Clean data improves deliverability

    Removing bounced and invalid contacts lowers bounce rates and protects your sender reputation, which keeps campaigns reaching real inboxes. Fewer hard bounces also protect your sending domain, which keeps important emails reaching people for years.

  • Contact counts drop to what you pay for

    HubSpot pricing for marketing contacts depends on how many you hold. Clearing out dead contacts can reduce the tier you pay for. Clearing out stale records can lower the bill and make reports about your real audience more meaningful.

  • Mistakes are less likely

    Matching by exact email address avoids the wrong-person errors that happen when hundreds of rows are handled by hand. Precise matching keeps the cleanup safe, and the confirmation tells you which entries did not match and need review.

  • A confirmation you can keep

    The count of removed and unmatched addresses is emailed to you, giving a simple record that the request was carried out. That record is useful if a privacy team or a regulator later asks you to show that a request was handled.

How it works

What happens, step by step

  1. When you send ClickRuntime a list of email addresses, the automation reads every address in it.

  2. It looks up the matching contact in HubSpot for each one.

  3. The matching contacts are archived in batches.

  4. You get an email with how many addresses were received and how many contacts were removed.

Before it runs live

  • Connect HubSpot
  • Paste your automation's link into the other app's webhook settings

What you get

RunsThe moment it happens
Remove a list of contacts from HubSpotjust nowSucceeded
Email · Removed 312 HubSpot contacts340 emails received, 312 matching contacts deleted.

Build your own

Need it to work differently?

This template is a starting point. Copy the prompt and change it, or describe a different automation from scratch, with your own conditions, more apps or an AI step. Your assistant writes it, tests it and runs it on ClickRuntime.
  • Your own rules

    Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.

  • Any number of apps

    One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.

  • AI where it helps

    Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.

  • On a schedule or on each event

    Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.

Changes you can ask for

  • Act only on the items that match your own rules, and skip the rest
  • Add an AI step, for example to summarize, sort or draft a reply
  • Add another app, for example also send it to Slack
  • Combine it with other HubSpot steps into one automation

Under the hood

The code that runs this automation

This is the Python script that runs each time the automation starts. Your AI assistant writes it for you when you send the prompt, and you allow each step in your assistant. To change how the automation works, describe the change to your assistant and it updates the script for you. For every function it can use, see the script reference.
bulk_delete_contacts_from_a_list.pyexample
import csv, io, re
from clickruntime import on_event, credentials, http, notify

API = "https://api.hubapi.com/crm/v3/objects/contacts"

@on_event
def handle(event):
    text = event.body or ""
    emails = sorted({c.strip().lower() for row in csv.reader(io.StringIO(text)) for c in row
                     if re.match(r"[^@\s]+@[^@\s]+\.\w+", c.strip())})
    headers = {"Authorization": f"Bearer {credentials.connection('hubspot', 'work')}"}
    ids = []
    for i in range(0, len(emails), 100):
        found = http.post(f"{API}/search", headers=headers, json={"limit": 100, "filterGroups": [{"filters": [
            {"propertyName": "email", "operator": "IN", "values": emails[i:i + 100]}]}]}).json()["results"]
        ids += [c["id"] for c in found]
    for i in range(0, len(ids), 100):
        http.post(f"{API}/batch/archive", headers=headers,
                  json={"inputs": [{"id": cid} for cid in ids[i:i + 100]]}).raise_for_status()
    notify.email_me(f"Removed {len(ids)} HubSpot contacts", f"{len(emails)} emails received, {len(ids)} matching contacts deleted.")
    return {"emails": len(emails), "deleted": len(ids)}

FAQ

Common questions

Are the contacts permanently deleted?
They are archived using HubSpot's delete endpoint, which removes them from the portal. HubSpot may allow restoration for a period afterward, and a permanent erasure for privacy purposes may need a separate step in HubSpot, so check which you need.
What happens to addresses that are not in HubSpot?
They are skipped and listed in the confirmation email, so you know which entries were not found. Typos and alternate addresses are the usual reasons, and you can fix and resend them. Fix the typos and send the list again.
Is there a limit on how many emails I can send at once?
Contacts are processed in batches to stay within HubSpot's rate limits, so a list of thousands works, but takes longer. For very large lists, splitting them across a few requests is sensible. Large lists are simply processed in several steps.
What permissions does it need?
crm.objects.contacts.write. Nothing else in your accounts is used.
Does it need AI?
No. It runs without AI, so it doesn't use your plan's AI allowance.
How many runs does it use?
One run for each event the app sends.
Can I change how it works?
Yes. Describe the change to your AI assistant, for example a different schedule, channel or filter. It updates the automation, tests it and tells you what changed.

Set up “Remove a list of contacts from HubSpot” from your assistant

Copy the prompt above, or connect your assistant first. Free plan, no credit card.