review-bounced-contacts — Claude Code skill: HubSpot bounce triage
A weekly manual pass over contacts with 3+ bounces: delete them or try to recover. Keeps suppression from going too far while bad records still leave.
npx skills add TomGranot/hubspot-admin-skills --skill review-bounced-contacts -a claude-codeWhat review-bounced-contacts does
This skill lays out a weekly process for contacts carrying the email_health_flag. The bounce monitoring workflow already suppresses them automatically, yet a person still has to choose between permanent deletion and recovery. A Python snippet calls the CRM Search API and exports the flagged contacts to CSV, pulling email, name, company, bounce reason, lifecycle stage and owner.
Each contact then gets three checks: does the domain still resolve (MX lookup), is this a known customer, and was the bounce hard or soft. The decision table sends a dead domain straight to deletion, while a live domain with a soft bounce stays suppressed until the next quarter. Afterwards you delete the marked records through the UI or a batch delete, clear email_health_flag on everything you reviewed, and log the counts for the quarterly report.
You need the bounce monitoring workflow running and the email_health_flag property on contacts before this makes sense. Scripted pre-filtering wants a HubSpot key in HUBSPOT_ACCESS_TOKEN inside .env; a legacy private app token works too. Deleted contacts sit in HubSpot's recycling bin for 90 days, and that window is the only chance to bring them back.
What it helps with
- work through contacts with three or more bounces each week
- tell a hard bounce from a soft one before deleting a real customer
- export flagged contacts to CSV for a human to review
- clear
email_health_flagonce the review is done - count deleted versus kept contacts for the quarterly report
Example prompts for the agent
- Pull every contact with
email_health_flagset through the CRM Search API and save them to CSV - For each flagged contact, check the domain and deal history and tell me whether to delete or recover
- Clear
email_health_flagon the contacts I reviewed and count how many we deleted
How to install review-bounced-contacts
1Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill review-bounced-contacts -a claude-code2Manually: put the files in place
~/.claude/skills/review-bounced-contacts/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/review-bounced-contacts/
1Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill review-bounced-contacts -a codex2Manually: put the files in place
.agents/skills/review-bounced-contacts/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill review-bounced-contacts -a cursor2Manually: put the files in place
.cursor/skills/review-bounced-contacts/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install TomGranot/hubspot-admin-skills review-bounced-contacts2Manually: put the files in place
.github/skills/review-bounced-contacts/SKILL.md1Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill review-bounced-contacts -a gemini-cli2Platform CLI
gemini skills install https://github.com/TomGranot/hubspot-admin-skills --path skills/review-bounced-contactsManually: put the files in place
.devin/skills/review-bounced-contacts/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill review-bounced-contacts -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about review-bounced-contacts
How do I install review-bounced-contacts in Claude Code?
Run npx skills add TomGranot/hubspot-admin-skills --skill review-bounced-contacts -a claude-code. The skill lands at ~/.claude/skills/review-bounced-contacts/SKILL.md.
What does review-bounced-contacts do?
It walks through a weekly review of contacts with 3+ bounces: export via the CRM Search API, check the domain and bounce type, decide delete or recover, then clear the flag and log the outcome.
What do I need before using it?
An active bounce monitoring workflow, the email_health_flag property on contacts, and a HubSpot key in HUBSPOT_ACCESS_TOKEN in .env for the scripted export.
Source text
SKILL.md · MIT
---
name: review-bounced-contacts
description: "Weekly manual review of contacts with 3+ bounce events. Decide whether to delete or attempt recovery for each flagged contact. Prevents over-suppression while removing truly bad data."
license: MIT
metadata:
author: tomgranot
version: "1.1"
category: ongoing-maintenance
---
# Review Bounced Contacts
A weekly manual review process for contacts flagged with 3+ bounces. The bounce monitoring workflow auto-suppresses these contacts, but a human should decide whether to permanently delete or attempt recovery.
## Prerequisites
- Bounce monitoring workflow active (run `/bounce-monitoring-workflow` first)
- `email_health_flag` custom property exists on contacts
- A HubSpot service key (`HUBSPOT_ACCESS_TOKEN` in `.env`; an existing legacy private app token also works) for scripted pre-filtering
## Step-by-Step Instructions
### Stage 1: Before
Use the CRM Search API to pull contacts where `email_health_flag` is set:
```python
import os, requests
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.environ["HUBSPOT_ACCESS_TOKEN"]
BASE = "https://api.hubapi.com"
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
resp = requests.post(f"{BASE}/crm/v3/objects/contacts/search", headers=HEADERS, json={
"filterGroups": [{"filters": [
{"propertyName": "email_health_flag", "operator": "EQ", "value": "true"},
]}],
"properties": ["email", "firstname", "lastname", "company",
"hs_email_bounce", "hs_email_hard_bounce_reason_enum",
"lifecyclestage", "hubspot_owner_id"],
"limit": 100,
})
resp.raise_for_status()
results = resp.json()["results"]
```
Export results to a CSV for review.
### Stage 2: Execute — Review Each Contact
For each flagged contact, check:
1. **Is the email domain active?** Run a quick MX record lookup or visit the domain.
2. **Is this a known customer or high-value contact?** Check lifecycle stage and deal history.
3. **What is the bounce reason?** Hard bounce (invalid mailbox) vs. soft bounce (mailbox full, temporary error).
**Decision matrix:**
| Domain active? | High value? | Bounce type | Action |
|---------------|-------------|-------------|--------|
| No | Any | Any | Delete |
| Yes | No | Hard | Delete |
| Yes | No | Soft | Keep suppressed, recheck next quarter |
| Yes | Yes | Hard | Attempt to find updated email |
| Yes | Yes | Soft | Keep suppressed, monitor |
### Stage 3: After — Apply Decisions and Log
1. **Delete** contacts marked for deletion via the HubSpot UI or API batch delete.
2. **Clear** the `email_health_flag` on all reviewed contacts.
3. Log the review results (deleted count, kept count, recovery attempts) for the quarterly report.
## Rollback
- Deleted contacts can be restored from HubSpot's recycling bin within 90 days.
- Contacts kept as suppressed can be restored to marketing status via a workflow or manual update in the UI.
## MCP Note
This weekly triage is exactly the interactive, judgment-heavy work HubSpot's MCP server is good at (see `/connect-hubspot-mcp`): ask Claude to pull each flagged contact's details, deal history, and bounce reason conversationally while you decide delete-vs-recover.
## Frequency
Run weekly, ideally Monday morning. Should take 5-15 minutes depending on volume. If volume exceeds 50 contacts per week, investigate the root cause (bad list source, form spam, etc.).
© tomgranot · MIT · TomGranot/hubspot-admin-skills