Connecting JobCannon to HubSpot
OAuth setup for the JobCannon HubSpot integration: the connect flow, the 23 custom properties JobCannon creates, the partial-progress sweep, and troubleshooting.
HubSpot is a CRM, not an ATS, and the integration works the other way round from the ATS adapters: nothing in HubSpot orders an assessment. Your team sends invitations from JobCannon, and every completed assessment is upserted onto the matching HubSpot Contact by email.
Quick reference
| Property | Value |
|---|---|
| Auth method | OAuth 2.0 (HubSpot public app) |
| API base | https://api.hubapi.com |
| Identity key | Contact email |
| Endpoint used | POST /crm/v3/objects/contacts/batch/upsert |
| Idempotency | Upsert by email — re-pushing is safe, no duplicate contacts |
| Custom properties created | 23, all under jobcannon_assessments |
| Retry cadence | Every 15 minutes |
| Partial-progress sweep | Daily at 02:00 UTC |
Prerequisites
- HubSpot admin access — Settings → Integrations → Connected Apps
- A writable Contacts schema (default on every HubSpot tier)
- A JobCannon organisation on a Business plan
Step 1: Connect the portal
- In your JobCannon admin, open Integrations for your organisation.
- On the HubSpot row, click Connect HubSpot.
- Approve the scopes. Required:
oauth,crm.objects.contacts.read,crm.objects.contacts.write,crm.schemas.contacts.read,crm.schemas.contacts.write. Optional:crm.objects.companies.read,crm.objects.deals.read. - HubSpot redirects back and the row flips to Connected.
If your portal enforces an app allowlist, an admin has to add JobCannon before step 3 will succeed.
Step 2: What JobCannon creates
On first connect, a one-shot bootstrap creates the property infrastructure. You do not create anything by hand.
Property group: jobcannon_assessments, on the Contact object.
Properties created: 23. The full table, with the exact values each enumeration accepts, is in the score mapping guide — it is generated from the same list the integration creates, so it cannot drift.
Bootstrap is idempotent and 409-tolerant. Resync properties on the integration row re-creates anything missing and overwrites nothing.
Step 3: How a candidate reaches a contact
- An admin sends an invitation from JobCannon.
- The candidate completes the assessments. The email they complete under is the one your team entered.
- When the invitation reaches completed, JobCannon batch-upserts to HubSpot keyed on that email.
- Existing contact → updated in place. New email → HubSpot creates the contact.
Partial progress is surfaced too: a sweep at 02:00 UTC pushes a snapshot of in-progress invitations, so a candidate who has finished DISC but not Big Five still appears with what they have.
Step 4: Troubleshooting
Row shows "Not connected". Either the OAuth handshake did not finish, or someone revoked the app inside HubSpot. Click Connect HubSpot again.
Last sync is behind. HubSpot rate-limits writes; the retry queue runs every 15 minutes. Wait one cycle. If a single invitation is stuck for more than an hour, check the integration row for an error banner.
Properties vanished from a contact. Someone deleted the property group or individual jc_* properties in HubSpot. Click Resync properties — only missing items are re-created.
"Must reconnect" after a token revoke. HubSpot rotates OAuth tokens and JobCannon refreshes them transparently, but a user disconnecting the app in HubSpot's UI makes the refresh fail with 401. Reconnect. No data is lost; the JobCannon-side sync log is intact.
**jc_result_url points at /business/dashboard/invites/....** Correct. That link is for signed-in members of your JobCannon Business account — it is the result as your admins see it. Sent to someone outside the account it lands on a sign-in screen.
Vendor docs: https://developers.hubspot.com/docs/api/crm/contacts OAuth scopes: https://developers.hubspot.com/docs/api/working-with-oauth Support: partners@jobcannon.io