# Sync new Teachable students into HubSpot contacts

> Every 30 minutes, add new course buyers to HubSpot as customer contacts so sales and success see who bought what without lifting a finger.

- Workflow type: agent
- Services: Teachable, HubSpot
- Categories: Sales, Operations
- Published: 2026-07-11

## What it does

- Watches your Teachable school for new student purchases every 30 minutes and pushes them into HubSpot.
- Creates a new HubSpot contact if the email is new, or updates the existing one if the buyer is already in your CRM.
- Sets the contact's lifecycle stage to Customer and stamps the course name and enrollment date on the record.
- Logs any students it could not match cleanly so you can review them by hand.

## What you'll need

- A Teachable school on a plan that includes API access, and permission to generate an API key.
- A HubSpot account where you can sign in and grant permission to create and update contacts.
- Optional: a couple of custom contact properties in HubSpot (for example, enrolled course and enrollment date). The workflow will fall back to a standard note if you skip this step.

## Prompt

Build an agent workflow that syncs new Teachable students into HubSpot as CRM contacts so sales and customer success have a single source of truth for course buyers.

Trigger: cron, every 30 minutes.

On each run, the agent should:

1. Call Teachable List Transactions to find sales transactions created since the last run. Track the last-run timestamp in workflow state so we do not reprocess old rows. Teachable notes that new transactions can take up to two minutes to appear, so overlap the window by a couple of minutes to be safe. If a transaction is missing enrollment context, fall back to Teachable Get User for the buyer to pull their course enrollments.

2. Normalize each student: lowercase and trim the email, capture first and last name (split from Teachable's name field if needed), and record the course name and enrollment date (the transaction's purchased_at or the enrollment's enrolled_at).

3. Group transactions by student. If the same buyer appears in multiple new transactions this run (multiple courses purchased), merge them into a single HubSpot update per contact so we do not overwrite our own work mid-batch. Prefer the most recent course and enrollment date, but include all course names in the custom field (comma-separated) if there is more than one.

4. Look up the HubSpot contact schema once per run using HubSpot List Properties for the contacts object. Detect whether the school's preferred custom properties exist (for example, enrolled_course, enrollment_date, or any obvious course/enrollment field). If they do, write to them. If they do not, write the same information into the standard notes or hs_content_membership_notes property so it is not lost.

5. Call HubSpot Batch Upsert Contacts (matched on email as the idProperty) with up to 100 contacts per call. Set email, firstname, lastname, lifecyclestage=customer, and the course/enrollment fields resolved in step 4. Chunk larger sets across multiple batch calls.

6. For any student the agent could not reconcile (missing email, invalid email format, batch upsert error), log an entry to workflow output listing the Teachable transaction id, the buyer's name if known, and the reason. Do not fail the whole run for these; keep going and report at the end.

At the end of each run, produce a short summary: how many transactions were seen, how many contacts were created vs updated in HubSpot, and any students that could not be reconciled. Persist the new high-water-mark timestamp so the next run picks up cleanly.

Integrations: Teachable and HubSpot.

## How to customize

- Change how often it runs. Every 30 minutes is a good default, but hourly or every 15 minutes both work.
- Decide what lifecycle stage new buyers should land in. Customer is the most common choice, but you can send them to Opportunity or a custom stage instead.
- Pick which fields you care about writing back. First name, last name, course name, and enrollment date are the usual set, but you can add coupon code, price paid, or affiliate.
- Filter which purchases sync. You can skip free enrollments, sync only a specific course, or only include paid transactions.

## FAQ

### Will this create duplicate contacts in HubSpot?

No. Every student is matched to HubSpot by email address, and the match is case-insensitive. If the buyer already exists, the workflow updates their record instead of creating a new one.

### What happens if I do not have custom properties set up in HubSpot?

The workflow will still create and update contacts and set their lifecycle stage. If it cannot find your custom course or enrollment-date property, it writes that context into a standard notes field instead so nothing is lost.

### What if the same student buys two courses in the same 30 minute window?

The workflow groups multiple purchases from the same buyer into a single HubSpot update, so their contact is not overwritten mid-sync.

### Does this work for free enrollments and coupon signups too?

Yes by default, but you can tell the workflow to only sync paid transactions if you want your CRM to reflect real customers only.

### How do I know if a student could not be synced?

Any student the workflow could not reconcile, for example a purchase with no email, is written to a log so you can review and fix them manually.

Use this prompt in General Input: https://www.generalinput.com/prompts/sync-new-teachable-students-into-hubspot-contacts