Skip to content
Solutions Blueprint

Custom SIS-to-HubSpot Integration for a Health Sciences University's Admissions Pipeline

Hero featured image

A private chiropractic and health-sciences university ran its admissions pipeline through a Student Information System with no published API and no native HubSpot connector, so every applicant record had to be reconciled by hand. Salted Stone built a bidirectional integration on AWS Lambda and API Gateway keyed on the SIS's own identifiers rather than email, since one contact can carry more than one enrollment record. A property change on the HubSpot Contact fires the sync toward the SIS in near real time, and an hourly poll pulls updates back.

Executive Summary

context-header-icon

Context

The university enrolls students into chiropractic and allied health programs and runs admissions through HubSpot Sales Hub, but its Student Information System, Anthology's Campus Nexus Student, had never exposed an API or a connector for any CRM. Every applicant's enrollment status lived in one system while every interaction with that applicant lived in another, with no supported path to keep the two in sync.

what-we-built-header-icon

What We Built

We built a bidirectional AWS Lambda and API Gateway integration that pushes a HubSpot Contact to the SIS the moment its program status changes to Applicant, and pulls SIS updates back on an hourly poll, replacing a manual, dual-entry admissions workflow with one governed sync.

tech-stack-header-icon

Tech Stack

  • AWS Lambda
  • AWS API Gateway
  • AWS CloudWatch
  • HubSpot webhooks (contact.propertyChange)
  • Anthology Campus Nexus Student SIS
  • Slack

Not a fit if there is no internal owner ready to take on the sync after launch. A bidirectional build against an SIS with no published API is reverse engineered against a live vendor's private data model, and it needs someone on the Admissions or IT side monitoring the CloudWatch alerts and owning fixes when the vendor changes something upstream, not a system that runs itself indefinitely once it ships.

the-challenge-header-icon

The Challenge

Admissions counselors tracked each applicant's program status inside HubSpot, but Campus Nexus Student held the enrollment record of truth, and Anthology, the SIS vendor, had never published an API or an integration path. Every time a prospect moved from applicant to enrolled, a staff member checked both systems by hand and updated whichever one had not caught up, and because a single contact could hold more than one SIS enrollment, matching on email alone produced false matches. As admissions volume grew, the two systems drifted further apart between manual checks, and a stale status left a counselor working from the wrong picture of where an applicant stood.

our-approach-header-icon

Our Approach

The team first looked for a native connector between HubSpot and Campus Nexus Student, but Anthology had never published one or handed over API documentation, so an off-the-shelf integration was never an option. Salted Stone built custom middleware on AWS Lambda and API Gateway instead, one of the custom API layers an undocumented vendor leaves you to write, with CloudWatch as the logging layer. The sync triggers when a Contact's program_status_stage changes to Applicant, firing a webhook that pushes the record to the SIS in near real time. Rather than match on email, which one contact could hold more than once across separate SIS enrollments, the integration matches on SIS-issued identifiers, sis_id and adenroll_id, on both the Contact and a custom Program Status object. The return path runs on an hourly poll instead, pulling only SIS records modified in the past hour, a trade against real-time sync for a build that did not depend on the SIS exposing anything it was not built to expose. On failure, the middleware halts, logs to CloudWatch, and alerts the development team by email and Slack.

impact-header-icon

Impact

check-icon

Admissions no longer reconciles two systems by hand

Counselors used to check both HubSpot and the SIS separately whenever an applicant's status might have moved, because nothing kept the two in sync automatically. The bidirectional build removed that step: a property change on the Contact now pushes to the SIS on its own, and the hourly return poll brings updates back without anyone re-entering them, so staff time goes to admissions work rather than reconciliation.

check-icon

Applicant status updates without a manual check

Before the integration, an applicant's move to enrolled or withdrawn could sit unreflected in HubSpot until someone checked the SIS by hand. Now the webhook on program_status_stage fires the moment that stage changes to Applicant, so the record Admissions works from reflects the SIS side within the hour instead of whenever staff time allowed.

check-icon

Multiple enrollments per contact no longer break the match

Matching on email alone would have merged or missed records whenever a single contact held more than one SIS enrollment, which happens whenever a prospect applies to more than one program. Keying the sync on SIS-issued identifiers, sis_id and adenroll_id, on both the Contact and the Program Status object instead means each enrollment resolves to the right record regardless of how many times that prospect has applied.

check-icon

A failed sync surfaces before a record goes stale

A silent sync failure would have let a wrong status sit unnoticed until someone caught it downstream. Because the integration halts on failure, logs to CloudWatch, and alerts the development team by email and Slack the moment something breaks, a bad sync gets fixed before it reaches a counselor's view of an applicant.

Technical Blueprint
1

A HubSpot workflow watches the Contact property program_status_stage and fires a webhook, subscription type contact.propertyChange, the moment its value changes to Applicant. That single property change is the only event that starts the HubSpot-to-SIS push.

2

The integration matches records on sis_id, adenroll_id, and program_sis_id or pv_sis_id rather than email, carried on both the HubSpot Contact and a custom Program Status object. Keying on identifiers the SIS itself issues is what lets one contact hold more than one enrollment without the sync merging or misrouting either one.

3

The SIS-to-HubSpot direction runs on an hourly poll rather than a webhook, since Campus Nexus Student had no event mechanism to subscribe to. Each run pulls only the records modified in the past hour, keeping the poll load bounded instead of rereading the entire enrollment table.

4

When either side of the sync fails, the integration halts rather than writing a partial update, and logs the failure to AWS CloudWatch. An email and an internal Slack alert notify the development team immediately, so a broken sync gets attention before it accumulates a backlog.

Diagram of a HubSpot-to-SIS sync through a custom AWS integration layer, webhook push one way and hourly poll the other.

HubSpot AWS integration SIS Alerts HubSpot Contact + Program Status object AWS Lambda + API Gateway custom integration layer Campus Nexus Student Student Information System CloudWatch failure log Slack alert dev team notification stage changes to Applicant mechanism 1 push via SIS ID mechanism 1 hourly poll past hour mechanism 1 writes update back mechanism 1 logs on failure mechanism 1 alerts dev team mechanism 1

FAQ

Why not just match HubSpot and the SIS on email address?

Because one prospective student can generate more than one SIS enrollment record, email alone would merge records that should stay separate or miss ones that should match. The integration keys on identifiers the SIS itself issues, sis_id and adenroll_id, carried on both the HubSpot Contact and a custom Program Status object, so each enrollment resolves correctly even when a contact has applied more than once.

What happens if the SIS integration fails partway through a sync?

The sync halts rather than writing a partial or guessed update, so a failure never leaves a record in an inconsistent state. It logs the failure to AWS CloudWatch and sends an email plus an internal Slack alert, so someone is notified and can act before the failure becomes a backlog of unsynced applicant records.

Continue reading

Hero featured image
209049082793

Luxury yacht manufacturer: CRM governance, 16.9% MQL-to-SQL

Hero featured image
209049052783

$500M+ telecom provider: one CPQ for MSP and ISP catalogs

Hero featured image
209049052785

Health insurance web broker: NPN hierarchies in HubSpot

Hero featured image
209049052787

$50M+ telehealth provider: HIPAA-compliant clinical ERP sync

Hero featured image
209049052787

$50M+ telehealth provider: attribution recovered via API fix

Hero featured image
209049052786

Environmental IoT provider: partner directory routes leads

Hero featured image
209053190299

$100M+ real estate tech firm: automated KYC gates and SSO

Hero featured image
209049052785

$1B+ financial data provider: Pardot and Eloqua into HubSpot

Hero featured image
209053177394

Global abrasives producer: 40+ sites from Kentico to HubSpot

Hero featured image
209049082792

Global abrasives producer: 13 dashboards consolidated to one

Hero featured image
209049052787

Medical device maker: five regional domains into one CMS

Hero featured image
209049052787

Medical device maker: automated clinical triage in HubSpot

Hero featured image
209049052787

Multi-site dental group: lifecycle logic rebuilt, true ROI

Hero featured image
209049052787

Multi-site dental group: assessment tool for lead quality

Hero featured image
209049082794

K-12 Catholic diocese: 80 schools on one HubDB lead system

Hero featured image
209049052787

Cell therapy biotech: HubSpot CMS migration, 92 speed score

Hero featured image
209049052787

Cell therapy biotech: 40-hour enablement and lead routing

Hero featured image
209049082794

Wellness training provider: 925k records moved to HubSpot

Hero featured image
209049052786

Cybersecurity trainer: 595 workflows audited for debt

Hero featured image
209049052785

Tier 1 auto F&I provider: 14,000% CTA lift, 21% PVR lift

Hero featured image
209049052785

Mexican retail bank: Infobip to Intercom via Apache NiFi

Hero featured image
209049052786

Global streaming platform: ETL middleware feeds Customer.io

Hero featured image
209049052786

Global streaming platform: usage milestones trigger upsell

Hero featured image
209049052786

Cloud and edge provider: Intercom to Salesforce via MuleSoft

Hero featured image
209049052785

$50M+ FinTech SaaS provider: advisor onboarding 30% faster

Hero featured image
209049082792

Mining autonomy provider: global consent and data governance

Hero featured image
209053177394

Industrial IoT division: compliant list purge, leads 3 to 62

Hero featured image
209053177394

Industrial IoT division: 25,000 records merged, one portal

Hero featured image
209049052786

Logistics SaaS portfolio: Salesforce sync rebuilt on Tray.io

Hero featured image
209049052786

Logistics SaaS portfolio: brands consolidated into HubSpot

footerCTA footerCTA-mobile
Spice up your inbox
Sign up for our newsletter
Don't worry - we only average, like, two emojis per subject line.