Skip to main content
JobCannon

Connecting JobCannon to HubSpot

Step-by-step OAuth setup for the JobCannon HubSpot integration. Covers connect flow, the custom property group JobCannon creates, partial-progress sweep behavior, and troubleshooting (token revoke, deleted properties, stuck syncs).

~920 wordsVendor docs →

Connecting JobCannon to HubSpot


JobCannon integrates with HubSpot via OAuth 2.0. Once your admin authorizes the JobCannon app on your portal, every completed B2B assessment is upserted onto the matching Contact record using the candidate's email as the identity key. This guide is written for your operations or RevOps team — the people who will live with the integration day-to-day.


Quick Reference


| Property | Value |
|----------|-------|
| Auth method | OAuth 2.0 (HubSpot Public App) |
| API base | https://api.hubapi.com |
| Identity key | Contact email (lowercased, trimmed) |
| Endpoint | POST /crm/v3/objects/contacts/batch/upsert |
| Idempotency | upsert by email — re-pushes are safe |
| Rate limit | 100 req/10s free, 150 req/10s paid (HubSpot tier) |
| Auto-create contact | Yes (when email is new to the portal) |
| Retry on 429/5xx | Yes — exponential backoff up to 6 attempts |
| Sandbox supported | Yes (use a HubSpot developer test portal) |

Prerequisites


  • A HubSpot account with admin access (you need Settings → Integrations → Connected Apps)
  • The Contacts schema must be writable (default on all HubSpot tiers)
  • Your JobCannon account must be on a Business-mode plan with at least one organization configured

  • Step 1: Connect your portal


    1. Sign in to your JobCannon admin and open the Integrations section for your org.

    2. Find the **HubSpot** row and click **Connect HubSpot**.

    3. HubSpot will ask you to sign in and approve a small set of scopes:

    - oauth (token lifecycle)

    - crm.objects.contacts.read

    - crm.objects.contacts.write

    - crm.schemas.contacts.read

    - crm.schemas.contacts.write

    4. Approve. You will be redirected back to JobCannon with a green confirmation banner and the connection status will flip to **Connected**.


    If your team uses HubSpot's strict app-allowlist policy, an admin may need to add JobCannon to the allowlist before step 3 succeeds.


    Step 2: What JobCannon creates in your portal


    The first time you connect, JobCannon calls a one-shot bootstrap routine to create the custom-property infrastructure used for assessment data. You do not need to create any properties yourself.


    **Property group:** `jobcannon_assessments` (label: "JobCannon Assessments"). All custom properties land in this group on the Contact object so they are easy to find in your portal under Settings → Properties.


    **Custom properties created** (17 total — see the Score Mapping doc for the full table):

  • DISC: jc_disc_d, jc_disc_i, jc_disc_s, jc_disc_c
  • Big Five: jc_bigfive_o, jc_bigfive_c, jc_bigfive_e, jc_bigfive_a, jc_bigfive_n
  • Cognitive: jc_iq_score
  • Integrity: jc_integrity_score
  • Type-based: jc_mbti_type, jc_riasec_holland
  • Status + audit: jc_test_status, jc_result_url, jc_completed_at, jc_invitation_id

  • Bootstrap is idempotent. Re-running it (the **Resync properties** button on the integration row) will only create missing items — it never overwrites or duplicates anything.


    Step 3: How a candidate flows to a contact


    1. An admin in your org sends an assessment invite via JobCannon (Dashboard → Invites → New).

    2. The candidate completes the test(s) on JobCannon. The candidate's email is the same email your team used in the invite form.

    3. As soon as the invite reaches `status='completed'` (all assigned tests done) JobCannon calls HubSpot's batch upsert with that email as the identity.

    4. If the email exists in your portal, JobCannon updates the existing Contact with the JC properties + a link to the full result. If the email is new, HubSpot creates a fresh Contact record and stamps the JC properties on it.


    Partial completions are also surfaced: a daily sweep runs at 02:00 UTC and pushes a snapshot of in-progress invites so candidates who finished DISC but are stuck on Big Five still appear in your CRM with what they have so far.


    Step 4: Troubleshooting


    **The Connected pill is gray and shows "Not connected".**

    Either the OAuth handshake did not complete, or an admin in HubSpot revoked the app from your portal. Click **Connect HubSpot** again. If the connection had been live and was revoked, JobCannon will have sent a Telegram alert to your account owner.


    **Last sync time is hours behind real-world completions.**

    HubSpot rate-limits the API. JobCannon's retry queue runs every 5 minutes — wait one cycle. If the row sits stuck for more than 30 minutes on the same invite, an admin should check the integration row for an error banner and click **Resync properties** to re-run the bootstrap.


    **Custom properties disappeared from a Contact.**

    Someone deleted the `jobcannon_assessments` property group or specific jc_* properties in your portal. Open the integration page in JobCannon and click **Resync properties** — the bootstrap is 409-tolerant and will re-create only the missing items.


    **Token revoke / "must reconnect" message.**

    HubSpot's OAuth tokens rotate. JobCannon refreshes them transparently, but if a user disconnects the JobCannon app inside HubSpot's UI the refresh will fail with 401. You will see a banner asking the admin to click **Connect HubSpot** again. No data is lost — JobCannon's local sync log remains intact.


    **The result URL on the Contact points to /business/dashboard/invites/...**

    That is correct. The URL only works for users who are signed in to your JobCannon Business dashboard — it is the candidate's full result envelope as your admin sees it. Sharing the link externally will land on a sign-in screen.


    ---


    **Vendor docs:** https://developers.hubspot.com/docs/api/crm/contacts

    **OAuth scopes reference:** https://developers.hubspot.com/docs/api/working-with-oauth

    **Support:** [email protected]