Register your interest: Tag @Cody, get an agent
BlogResources

HubSpot and CodeWords: automating without fighting the workflows

Associations, the lifecycle stage that moves for reasons nobody remembers, HubSpot's own workflows and when to use them, and why deduplication matters more than anything you build.

Rithul PalazhiRithul Palazhi11 min read

Summarize with AI

HubSpot and CodeWords: automating without fighting the workflows
On this page

HubSpot is usually the system a company has had longest and cleaned least. Contacts arrive from forms, imports, integrations, and sales reps typing quickly, and by the time anybody wants to automate something, the underlying data has opinions of its own.

That shapes the order of work. Automating on top of a portal where the same company exists four times produces four times the mess, faster. The deduplication and the association hygiene come first, and they are also the most valuable automation available.

What we'll cover

Find out what already runs

HubSpot has its own automation, and much of it was configured by people who have since left.

Workflows act on records and can set properties, send email, create tasks, and rotate owners. There are usually more than anybody remembers and some have been running unnoticed for years.

Forms have their own follow-up behaviour attached.

Sequences send on behalf of individual reps.

Lead scoring adjusts properties on its own schedule.

Installed integrations write to records, and several may write to the same property.

Before building anything, list the active workflows and what each one changes. The common failure is an external automation setting a property while a HubSpot workflow sets it back, producing a record that flips and a bug nobody can reproduce because it depends on which ran last.

If HubSpot's own workflow can do the job, use it. External automation earns its place when the logic needs data HubSpot does not hold.

Associations, which carry the meaning

HubSpot's object model is contacts, companies, deals, tickets, and custom objects, joined by associations — and the associations are where most of the useful information lives.

Association labels describe the relationship, not just its existence. A contact associated with a deal as the decision maker is different from one associated as a technical contact, and automation that ignores labels treats them identically.

Contacts associate with companies by email domain automatically where that setting is on, which is convenient and wrong for anyone using a personal address.

Deals need their associations to be reportable. A deal with no associated company is invisible to half the reporting somebody will want.

Associations can be many-to-many, so a contact can sit on several deals, and an automation assuming one will pick an arbitrary member of a set.

Read and write associations deliberately. Most CRM automation disappointment traces back to records that are correct individually and not connected to each other.

What the HubSpot API reaches

CRM objects — contacts, companies, deals, tickets, and custom objects — support create, read, update, search, and batch operations.

Associations can be read and written, including labels.

Properties can be listed, including their types and options, which is worth reading rather than hard-coding since portals are heavily customised.

Engagements — notes, calls, emails, meetings, and tasks — can be created and read, which is how automation leaves a visible trail.

Workflows can be enrolled into, so external logic can hand off to HubSpot's own automation rather than duplicating it.

Webhooks notify on object changes, and delivery is at-least-once.

Lists can be read and, for static lists, modified.

Marketing email and forms have their own endpoints, with the usual consent considerations.

Connecting it to CodeWords

CodeWords connects to more than 3,000 integrations, and the connection is made once and reused.

  1. Open CodeWords and start a new automation.
  2. Describe what should happen in plain language to Cody, the automation builder: which object, what triggers it, and what should change.
  3. Authorize the connection with a private app scoped to the specific objects and permissions required.
  4. Describe the exceptions: a duplicate contact, a company that cannot be matched, a property whose options have changed.
  5. Test against a small, known set of records before anything runs across the portal.

You describe the outcome; Cody builds it, connects it, and deploys it. The free plan covers light use, with Pro at $39 per month and Business at $100 per month as usage grows; details are on the pricing page.

Seven automations worth building

Duplicate reporting. Contacts and companies that are probably the same, listed for review. Covered in detail below because it changes everything downstream.

Association repair. Contacts with no company, deals with no contact, and tickets attached to nothing, reported with a suggested match.

Enrichment from your own systems. Product usage, support history, and billing status written onto the record, so the sales team sees what is true rather than asking.

Handoff records that carry context. When a lead qualifies, create the deal with the relevant history attached as a note, rather than leaving the next person to reconstruct it.

Data quality reporting. Missing required properties, implausible values, and records that have not changed in a year while sitting in an active stage.

Two-way synchronisation with the system of record. Where another system owns a field — billing status, plan, account health — keep HubSpot informed and decide which direction wins.

Stale pipeline reporting. Deals with no activity, by owner and stage, reported to the person who can act rather than posted to a channel.

Deduplication, which comes first

The single most valuable thing to build, and the one most often skipped.

Match on more than email. The same person appears with a work address and a personal one. Name plus company, or a normalised phone number, catches what email alone misses.

Normalise before comparing. Lowercase, trim, strip punctuation from phone numbers, and remove the common company suffixes, or you will compare two strings that differ by a full stop.

Report, do not merge automatically. Merging is destructive and near-matches are sometimes genuinely different people. A weekly list somebody spends ten minutes on is safer and sufficient.

Deduplicate at the point of creation. The cheapest fix is the automation checking before it creates, which is where most new duplicates come from.

Fix companies as well as contacts. Duplicate companies distort every piece of account-level reporting, and they are harder to spot because nobody looks at the company list.

Lifecycle stages and why they move

Lifecycle stage is the property most likely to be written by several things at once.

HubSpot moves it forwards automatically under some settings, and by default it does not move backwards, which surprises people whose automation appears to have had no effect.

Workflows set it, frequently more than one.

Integrations set it, and marketing tools are particularly fond of it.

Reps set it manually, in the direction they consider correct.

Decide who owns this property, write that down, and make everything else read it rather than set it. Where automation must set it, log what changed it and why, because the question "why is this contact a customer?" comes up often and is otherwise unanswerable.

Marketing contacts, which cost money

A HubSpot-specific concern that catches teams out when automation starts creating records at volume.

Marketing contacts are billed differently from non-marketing ones, and an automation creating contacts indiscriminately can change what the portal costs.

Set the designation deliberately when creating. A contact created for operational reasons — a support requester, a billing contact — usually should not be marketable.

Consent is a separate matter from the designation. Legal basis to email somebody is recorded in subscription preferences, and nothing about creating a contact establishes it.

Imports are the usual culprit. A one-off import through an automation is the moment a portal's contact count jumps, and it is worth checking the designation before running one.

Report the count you are about to create before a bulk run, since a number on screen prompts the question that avoids an unpleasant invoice.

Building it so it survives

Use search before create. Every creating automation should look first, or it becomes a duplicate generator.

Make it idempotent. Store your source identifier in a custom property and key on it rather than on anything a person can edit.

Batch where volume warrants. Batch endpoints exist and are far kinder to your rate limit than a call per record.

Read property definitions rather than assuming. Dropdown options change, and writing an option that no longer exists fails in a way that is easy to miss.

Report the outcome. Records created, updated, skipped, and flagged as possible duplicates.

Limits worth knowing about

Rate limits depend on your subscription and app type, and bulk work needs batching and pacing rather than optimism.

Search has its own, tighter limits and is eventually consistent, so a record created and immediately searched for may not be found.

Property history is limited for some property types, which affects auditing after the fact.

Webhooks are at-least-once and can arrive out of order, so a later event may be processed before an earlier one.

Portal customisation varies enormously. An automation written against one portal's properties will not transfer to another without checking.

What to build first

Duplicate reporting: contacts and companies that are probably the same, matched on normalised email, name-plus-company, and phone, delivered as a weekly review list. It writes nothing, it takes little building, and it establishes what state the data is in before anything else depends on it.

Two habits make the difference. Show the evidence for each match — which fields agreed — so the person reviewing can decide in seconds rather than opening both records. And add the same check to any automation that creates records, since that is where tomorrow's duplicates come from.

Frequently asked questions

Should I use HubSpot workflows or external automation?

HubSpot workflows for anything driven entirely by data already in HubSpot. External automation when the logic needs product usage, billing, support history, or anything else HubSpot cannot see. Duplicating logic in both is the arrangement that causes properties to flip.

Why does a property keep changing back?

Because something else is setting it — usually a workflow, sometimes an integration. List what writes to that property, decide which one owns it, and make everything else read rather than write. This is the most common CRM automation bug and it is entirely a configuration problem.

How should automation handle duplicates?

Check before creating, and report existing ones rather than merging them. Merging is destructive and near-matches are sometimes different people. A short weekly review list handles it safely.

Why can my automation not find a record it just created?

Search is eventually consistent. Use the identifier returned when you created the record rather than searching for it, which is both faster and correct.

Do association labels matter?

Yes, and they are widely ignored. A decision maker and a technical contact on the same deal mean different things, and automation that treats every association identically produces reports and handoffs that are subtly wrong.

What should the integration's permissions be?

A private app scoped to the specific objects and actions it needs. Broad access makes it impossible to tell what changed a record, and a scoped app fails loudly when it tries to do something outside its remit, which is useful.

What is the most useful enrichment to write onto a contact?

Whatever the sales team currently asks somebody else for — usage, plan, open tickets, payment status. It is information you already hold, it is invisible in HubSpot, and putting it on the record removes a recurring interruption rather than adding a report.

Can automation creating contacts increase our HubSpot bill?

It can, because marketing contacts are billed differently. Set the designation deliberately when creating — operational contacts such as support requesters and billing contacts usually should not be marketable — and check the count before any bulk run.

Does creating a contact mean we can email them?

No. Legal basis to email is recorded in subscription preferences and is separate from the record existing or from its marketing designation. Automation should never treat record creation as consent.

Get started today

Your first workflow is free to build.

Describe what you need. Cody handles the build, the connections, and the deployment.