Skip to content

Repository files navigation

HubSpot State/Region Validator

This repository contains two scripts that scan HubSpot records and validate/normalize their State/Region and State/Region Code properties against a predefined list of US states, Canadian provinces, and Mexican states:

  • verify_company_states.py — validates Company records.
  • normalize_contact_states.py — normalizes Contact records.

Both provide automated corrections for common spelling errors and abbreviations, and offer an interactive interface to manually correct or skip records that cannot be resolved automatically. Records identified as being in countries outside the target regions (US, Canada, and Mexico) are automatically skipped.

Features

  • Paging Support: Fetches and processes all records in batches of 100 via HubSpot CRM v3 API.
  • Foreign Country Filtering: Automatically ignores records located outside of the target regions (US, Canada, and Mexico) if their country field is populated. This prevents false positive suggestion prompts for foreign state/region names (e.g., "Madrid" in Spain or "Bavaria" in Germany).
  • Fuzzy Matching: Automatically suggests spelling corrections for state/region names (e.g., misspelled names or variations).
  • Auto-expansion: Expands 2-letter abbreviations to their full names (e.g., CA -> California).
  • Country Disambiguation: Uses the record's country (US, Canada, Mexico) to resolve overlapping 2-letter codes (e.g., BC for British Columbia, Canada vs. Baja California, Mexico).
  • Auto-population: Automatically populates the 2-letter State/Region Code field if only the full name is present, or vice-versa when safe.
  • Interactive Correction Loop: Allows users to approve suggestions, enter manual entries, skip records, or quit.
  • Checkpointing: Automatically saves progress to a checkpoint file (company_states_checkpoint.json for companies, contact_states_checkpoint.json for contacts) so you can stop and resume either script at any time without losing progress.
  • Detailed Logging: Records actions to stdout and to a log file (verify_company_states.log for companies, normalize_contact_states.log for contacts).

Prerequisites

  • Python 3.6+
  • HubSpot Private App Token: Requires read/write access to CRM Company objects (for the company script) and/or CRM Contact objects (for the contact script).
  • HubSpot Portal ID: Your HubSpot Account/Portal ID (e.g., 12345678).

Setup Instructions

  1. Clone or Navigate to the Repository Directory:

    cd /path/to/state-validator
  2. Create and Activate a Virtual Environment (Recommended): On macOS/Linux:

    python3 -m venv .venv
    source .venv/bin/activate

    On Windows:

    python -m venv .venv
    .venv\Scripts\activate
  3. Install Dependencies:

    pip install -r requirements.txt

How to Run: Companies

Execute the script by providing your HubSpot Portal ID as a positional argument.

python verify_company_states.py <portal_id> [--state-code-prop <property_name>]

Arguments & Options

  • portal_id: (Required) Your HubSpot account's Portal ID (e.g., 12345678).
  • --state-code-prop: (Optional) The internal API name of the State/Region Code property in HubSpot. Defaults to state_code. The script also automatically scans and checks for hs_state_code and state_region_code.

Example Run

python verify_company_states.py 12345678
  1. Token Input: You will be prompted to enter your HubSpot Private App Token securely:

    HubSpot Private App Token : 
    

    (Note: The characters will not display as you type for security.)

  2. Property Detection: The script will verify if the specified State/Region Code property exists. If the property is not found, you will be warned and asked if you want to proceed.

  3. Pre-scan: The script fetches all companies, bypasses empty records, and automatically corrects standard abbreviation or missing code cases.

  4. Interactive Validation Loop: For remaining invalid state/region values, the script prints details and prompts you for action:

    Company [1/15]: Acme Corp (acme.com) | ID: 123456789
      Current Country     : US
      Current State/Region: 'Californa'
      Current Code        : 'CA'
    ------------------------------------------------------------
      [Suggestion] Full Name: California
      [Suggestion] Code     : CA
    Choose action ([A]ccept Suggestion | [M]anual Entry | [S]kip | [Q]uit) [A]: 
    
    • [A]ccept Suggestion: Applies the suggested full name and/or code to the company in HubSpot.
    • [M]anual Entry: Prompts you to type a state name (must match allowed states or be explicitly overridden) and code.
    • [S]kip: Skips the company for this run.
    • [Q]uit: Safely saves progress to the checkpoint file and terminates execution.

How to Run: Contacts

The contact normalizer works the same way, but operates on Contact records. Execute it by providing your HubSpot Portal ID as a positional argument.

python normalize_contact_states.py <portal_id> [--state-code-prop <property_name>] [--test]

Arguments & Options

  • portal_id: (Required) Your HubSpot account's Portal ID (e.g., 12345678).
  • --state-code-prop: (Optional) The internal API name of the State/Region Code property on the Contact object. Defaults to state_code. The script also automatically scans and checks for hs_state_code and state_region_code.
  • --test: (Optional) Test mode. Fetches and processes only the first 100 contacts, so you can verify the script's behavior on a small sample before a full run. Updates are still written to HubSpot for those 100 contacts. The checkpoint file is retained after a test run, so a later full run resumes past the records already processed.

Example Run

python normalize_contact_states.py 12345678

The flow is identical to the company script: you are prompted for your Private App Token, the State/Region Code property is detected/verified, all contacts are fetched and pre-scanned (auto-correcting abbreviations, casing, and missing codes), and any remaining unresolved records enter the interactive validation loop. Contacts are displayed by name (or email if no name is set):

Contact [1/15]: Jane Doe (jane.doe@example.com) | ID: 123456789
  Current Country     : US
  Current State/Region: 'Californa'
  Current Code        : 'CA'
------------------------------------------------------------
  [Suggestion] Full Name: California
  [Suggestion] Code     : CA
Choose action ([A]ccept Suggestion | [M]anual Entry | [S]kip | [Q]uit) [A]:

Note: Portals typically contain far more contacts than companies, so the initial fetch and pre-scan may take a while. The checkpoint file means you can safely quit and resume at any time.


Resuming Progress

If you quit either script midway (using q or Ctrl+C), a checkpoint file will be saved — company_states_checkpoint.json for the company script, contact_states_checkpoint.json for the contact script. The next time you run that script, it will automatically detect the checkpoint and resume from where you left off. The checkpoint file is automatically deleted once all invalid records are successfully processed. The two scripts use separate checkpoint files, so they can be run independently without interfering with each other.


Log Output

All changes and exceptions are logged with timestamps in verify_company_states.log (companies) and normalize_contact_states.log (contacts). You can tail or inspect these files to verify what updates were applied to your HubSpot portal:

tail -f verify_company_states.log
tail -f normalize_contact_states.log

About

HubSpot Company and Contact State/Region Validator

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages