---
title: "HubSpot"
slug: hubspot
section: Integrations
status: stable
description: "Universal Application Architecture v4 — Application-centric object model, field authority, and the HubSpot/Globus boundary"
last-updated: 2026-10-07
---

# HubSpot

Universal Application Architecture v4 — Application-centric object model, field authority, and the HubSpot/Globus boundary

## Overview

HubSpot is the lead capture and pre-qualification CRM. The object model is Application-centric: Contact is the root identity, and a separate Application object owns pre-qualification state, status, readiness, and journey position. Per-application detail (work history, education, qualifier answers, documents) lives in child custom objects attached to the Application, not as flat properties on the Contact.

> **Authority Boundary**
>
> HubSpot owns lead data and pre-qualification. Globus owns post-handoff operations from the moment globus_applicant_id is written to the Contact. After that point, HubSpot retains marketing analytics but does not govern operational participant data.

## Object Model

The hierarchy: Contact is the root identity. Each Contact can have one or more Application records. Each Application owns its own Work Experience, Education, Qualifier Response, and Application Document children. Program and Season are sibling reference objects — Globus-locked, mirrored into HubSpot for association only.

Contact (root identity) 
└─ Application (central operational object) 
├─ Work Experience 
├─ Education 
├─ Qualifier Response 
└─ Application Document 
Program ← Globus-locked, mirrored by n8n 
Season ← Globus-locked, mirrored by n8n 
Country ← Globus-locked, mirrored by n8n 
(Program/Season associate to Application; Country associates to Qualifier Response) 
Qualifier Response → Country association. A Qualifier Response capturing country_of_residence associates to a Globus-locked Country record via globus_country_id / iso_code, rather than storing a free text country name. The raw string property is deprecated once the association is live — the association is the authoritative path to a canonical country. This gives pre-qualification rules a stable anchor to evaluate country-based eligibility against.

## Field Authority

Every cross-system field has one owner. The owning side is the source of truth; the other side either does not hold the field or mirrors it read-only.

| Field | Owner | Direction | Sync mechanism |
| --- | --- | --- | --- |
| Contact.globus_applicant_id | Globus | Globus → HubSpot (write-once) | n8n handoff workflow writes on first handoff; never overwritten |
| Contact.email / firstname / lastname / phone | HubSpot | HubSpot → Globus (on handoff) | n8n handoff workflow passes identity payload to Globus |
| Contact.lifecyclestage / hs_lead_status / hubspot_owner_id | HubSpot | HubSpot-only | Native HubSpot — not synced to Globus |
| Application.prequalification_state | HubSpot | HubSpot-only (pre-handoff) | Computed in HubSpot pre-qualification workflows |
| Application.application_status | HubSpot pre-handoff, Globus post-handoff | Authority transfers at handoff | Final HubSpot value passed in handoff; Globus owns thereafter |
| Application.readiness_score | HubSpot | HubSpot-only (pre-handoff) | Computed in HubSpot — not mirrored back from Globus |
| Application.journey_position | HubSpot pre-handoff, Globus post-handoff | Authority transfers at handoff | HubSpot tracks pre-qual journey; Globus tracks operational journey post-handoff |
| Application.handoff_at | n8n handoff workflow | Set once at handoff | Stamped by n8n during handoff workflow |
| Qualifier Response.* | HubSpot | HubSpot → Globus (on handoff) | All Qualifier Response records for the Application passed to Globus on handoff |
| Work Experience.* / Education.* | HubSpot | HubSpot → Globus (on handoff) | Child records passed in handoff payload |
| Application Document.* | HubSpot pre-handoff, Globus post-handoff | HubSpot → Globus (on handoff) | Pre-handoff uploads passed to Globus; post-handoff documents live in Globus |
| Program.* / Season.* | Globus | Globus → HubSpot (read-only mirror) | n8n catalog sync mirrors Globus catalog into HubSpot on schedule |
| Country.* | Globus | Globus → HubSpot (read-only mirror) | n8n catalog sync mirrors Globus system_lookups (group: country) into HubSpot on schedule |
| Qualifier Response.country_of_residence → Country | Globus (master data) | Association resolved in HubSpot, country record owned by Globus | HubSpot holds the association; the Country record it points to is Globus-locked |
| Program Ban List.* / Program Date Window.* | HubSpot | HubSpot-only (pre-handoff rules) | Manually / agent managed in HubSpot; evaluated by the n8n eligibility engine — not synced to Globus |

## Boundary

> **HubSpot owns lead capture and pre-qualification. Globus owns post-handoff operations.**
>
> The boundary is drawn at the first write of Contact.globus_applicant_id. Before that write, HubSpot is authoritative for the Contact, the Application, and all child records. After that write, Globus is authoritative for the operational lifecycle. HubSpot retains the historical record and marketing analytics but does not make further operational decisions about the participant.

HubSpot side (pre-handoff)

Lead capture, qualifier collection, pre-qualification scoring, readiness, marketing nurture, and the handoff trigger.

Globus side (post-handoff)

Operational application lifecycle, workflow execution, document review, SEVIS, placement, on-program, and completion — everything downstream of globus_applicant_id.

## Native Fields Rule

> **HubSpot-native fields are used as-is — no renaming, no repurposing.**
>
> Fields like lifecyclestage, hs_lead_status, and hubspot_owner_id retain their native HubSpot semantics. Do not rename them. Do not repurpose them to carry application-specific meaning. If a concept does not fit a native HubSpot field, add it as a property on the appropriate custom object (Application or one of its children), not as a renamed Contact property.

## Globus-Locked Objects

> **Program, Season, and Country are Globus-locked.**
>
> All three objects are created and updated only on the Globus side. n8n mirrors them into HubSpot on a catalog-sync schedule so Application records can associate to a Program and a Season, and Qualifier Response records can associate to a Country, all by reference. Program and Season are sourced from the Globus catalog; Country is sourced from Globus system_lookups (group: country). HubSpot copies are read-only — any direct edits made in HubSpot are out of contract and will be overwritten on the next sync. New programs, season activations, capacity changes, brand attribution, and country catalog changes all flow Globus → HubSpot, never the other way.

> **Forward reference: Country anchors SWT date eligibility.**
>
> Country is the planned anchor for SWT program date eligibility rules. A dedicated SWT Date Window object is planned (not yet built) to express per-country eligibility windows for the Summer Work Travel program. Until it exists, country-based eligibility is expressed through the Pre-Qualification Rules objects below.

## Environments and Custom Object Type IDs

> **Custom object type ids differ per environment. Never hardcode one.**
>
> The dev, qa and sandbox environments share one HubSpot portal (a sandbox account, portalId 51221012). Production uses a separate, standard portal (portalId 6768913) in which every custom object has its own auto-generated type id. A type id copied from the dev portal into a workflow therefore fails silently in prod (the 2026-10-01 incident: prod HubSpot handoffs to the Globus webhook never landed because the Flow 1 Application lookup used the dev id and HubSpot answered "Invalid object or event type id").

The canonical per-environment mapping lives in the n8n-workflows repo at workflows/hubspot-object-type-map.json, keyed by the schema's stable internal name rather than the numeric id. n8n workflows cannot read the repo at runtime, so each affected node embeds a small resolver keyed off the n8n host (the same rule the Dispatcher uses) with literals copied from that file; the file and the embedded values must be changed together.

| Object | dev / qa / sandbox | prod |
| --- | --- | --- |
| Application | 2-59396507 | 2-65515441 |
| Application Document | 2-59396510 | 2-66250331 |
| Program | 2-62092723 | 2-66243449 |
| Operational Cycle | 2-62709140 | 2-66255157 |
| Country | 2-63632118 | 2-66249648 |

Globus seasons are carried in HubSpot as the Operational Cycle object: legacy season events are routed to the same HubSpot object rather than a distinct season object. How the handlers resolve the ids is described in the n8n Automation Layer (Program / Operational Cycle Catalog Sync).

## Pre-Qualification Rules

Pre-qualification eligibility is a scalable, data-driven architecture: eligibility rules live as HubSpot custom objects that operations and agents manage directly, and an n8n eligibility engine evaluates an Application against them before handoff. Two rule objects exist today — Program Ban List and Program Date Window — both keyed to a Program and (for bans) a Globus-locked Country. This keeps rule changes a content edit, not a code change, and aligns with Universal Application Architecture v4 and the field-classification-contract: rules are HubSpot-owned content; the master data they reference (Program, Country) stays Globus-locked.

### Rules vs Master Data

> **Rules are HubSpot-owned content. Master data stays Globus-locked.**
>
> Pre-qualification rules (Program Ban List, Program Date Window) are HubSpot custom objects, managed manually or by agents, and changed as content — no deploy required. The master data those rules reference (Program, Season, Country) is Globus-locked, mirrored read-only into HubSpot. A rule may point at master data but can never edit it; conversely, rules are never synced back to Globus. The n8n eligibility engine reads both and writes only the outcome (prequalification_state) onto the Application.

The n8n workflow logic that evaluates these rules — trigger events, evaluation order, and error handling — is documented as the Pre-Qualification Eligibility Engine on the automation page.

## Migration Note

> **What changed from the old model**
>
> The previous model was Contact-centric: per-application data lived as flat qualifier_* properties on the Contact, and there was no separate Application object. Under the new model: All qualifier_* flat properties have been removed from Contact. Qualifier answers now live on the Qualifier Response custom object, one record per question. A new Application custom object is the central operational record. Work Experience, Education, Qualifier Response, and Application Document attach to Application — not to Contact. A new globus_applicant_id property on Contact is the permanent identity link to Globus, written once at handoff.

## Related References

The four cross-system flows that move data between HubSpot and Globus (catalog sync, handoff, metadata sync, notification routing) are documented in the n8n Automation Layer .

The delivery-confirmation contract for applicant-facing communications routed through HubSpot is documented in the Notification & Communication Model .
