tomgranot/hubspot-admin-skills/delete-no-email-contacts
Claude Code and agent skill by tomgranot/hubspot-admin-skills
- community
Checking that the SKILL.md file is still in the repository.
Delete contacts with no email address from a HubSpot CRM instance. These contacts cannot receive any communication and inflate billing. Fully automated via the HubSpot CRM Search and Batch Archive APIs.
Install
npx vskill@latest install tomgranot/hubspot-admin-skills/delete-no-email-contactsSKILL.md
Delete Contacts With No Email Address
Purpose
Contacts without an email address serve no functional purpose in a HubSpot Marketing Hub instance. They cannot receive marketing emails, sales sequences, or transactional messages. They inflate the billed contact count. This skill identifies and deletes them via the API.
Prerequisites
- A HubSpot service key (
HUBSPOT_ACCESS_TOKENin.env; an existing legacy private app token also works) withcrm.objects.contacts.readandcrm.objects.contacts.writescopes - Python 3.10+ with
uvfor package management - A
.envfile containingHUBSPOT_ACCESS_TOKEN
Scripts
Script paths are relative to this skill's directory. Run them from your project directory so .env, data/, and reports/ resolve there: prefix each path with wherever this skill is installed (skills/delete-no-email-contacts/ in a clone of the repo).
| Stage | Script | Run with | |
|---|---|---|---|
| Before | `scripts/before.py` | uv run scripts/before.py | |
| Execute | `scripts/execute.py` | uv run scripts/execute.py | |
| After | `scripts/after.py` | uv run scripts/after.py |
before.py counts contacts with no email and exports the CSV baseline. execute.py collects IDs, exports the audit CSV, and batch-archives (typed confirmation + safety threshold). after.py verifies zero remain.
Execution Pattern
This skill follows a 4-stage execution pattern: Plan -> Before -> Execute -> After.
Stage 1: Plan
Before writing any code, confirm these items with the user:
- Root cause: Ask whether any integrations (CRM sync, form tool, import process) are intentionally creating contacts without email. If so, fix the inflow first.
- Threshold: The default safety abort threshold is 500 contacts. If the user expects more, adjust the threshold in the execute script.
- Recovery window: Confirm the user understands that deleted contacts are recoverable for 90 days via HubSpot Settings > Data Management > Deleted Objects.
Stage 2: Before
Run a count query to establish the baseline. Save results for comparison.
Expected output: A count of contacts with no email and a sample record for sanity checking.
Present findings to the user before proceeding. Ask for explicit confirmation to continue.
Stage 3: Execute
Collect all contact IDs via paginated search, export a CSV audit trail, then batch-delete.
Key API details:
POST /crm/v3/objects/contacts/searchwithNOT_HAS_PROPERTYfilter onemail- Paginate with
aftercursor, 100 results per page POST /crm/v3/objects/contacts/batch/archiveaccepts up to 100 IDs per call- Successful archive returns HTTP 204 (no content)
Stage 4: After
Re-run the before-state query to confirm zero contacts remain.
Present results to the user. If new contacts appeared, investigate the source (form submissions, integrations, imports).
Safety Mechanisms
| Mechanism | Detail | |
|---|---|---|
| Abort threshold | Hard-coded at 500 contacts by default. If the search returns more, the script exits without deleting anything. Adjust only with explicit user confirmation. | |
| CSV audit trail | Every contact ID, name, and create date is exported to CSV before any deletion occurs. | |
| Confirmation prompt | Always present the Before State count to the user and wait for explicit confirmation before running Execute. | |
| 90-day recovery | Deleted contacts can be restored via HubSpot Settings > Data Management > Deleted Objects for 90 days. | |
| Archived contacts audit | After deletion, you can retrieve deleted contacts via the standard contacts endpoint with archived=true parameter to verify what was removed. |
Technical Gotchas
- `NOT_HAS_PROPERTY` vs `EQ ""`: Use
NOT_HAS_PROPERTYoperator, notEQwith an empty string. HubSpot treats "property not set" differently from "property set to empty string."
- Search API pagination limit: The HubSpot CRM Search API has a hard cap of 10,000 results per query. For this use case (typically a few hundred contacts), this is not an issue. If you encounter it, use segmented queries (e.g., filter by create date ranges).
- Rate limiting: The Search API allows 5 requests per second per token, separate from the general burst limit. The batch archive API is more restrictive. Use
time.sleep(0.5)between batch archive calls.
- Batch archive returns 204: A successful batch archive returns HTTP 204 with an empty body, not 200. Check for
status_code == 204.
- Contacts may reappear: If an integration or form is creating contacts without email, new ones will appear after deletion. Always investigate the root cause.
Rollback
- Deleted contacts are recoverable for 90 days via HubSpot Settings > Data Management > Deleted Objects.
- The execute script's CSV audit trail lists every deleted contact ID for selective restoration.
Setup
Create a .env file in the repo root:
No package install is needed — scripts carry PEP 723 inline metadata and run with `uv`, which resolves dependencies automatically:
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/delete-no-email-contacts/SKILL.md
Popularity
- Repository stars
- 56
- Repository forks
- 15
- 7-day trend score
- 20
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/tomgranot/hubspot-admin-skills/delete-no-email-contacts)