- Creates or updates a HubSpot contact whenever someone joins your Mighty Network, buys a plan, or is tagged
- Loads your existing members into HubSpot
- Reacts to HubSpot activity by tagging members or inviting new people to your Network
How it works
- Mighty → HubSpot: You register a webhook with the
createWebhookCallbackmutation. Mighty sends member events to your service, and your service writes them to HubSpot. - HubSpot → Mighty: A HubSpot workflow calls your service, and your service calls the Mighty API to tag or invite the person.
Before you begin
You need:- A Mighty Network on the Scale Plan or above, and a Host account on it. OAuth applications and webhooks are plan-gated features.
- A HubSpot account with permission to create a private app. The HubSpot → Mighty direction also needs workflows that can Send a webhook, which depends on your HubSpot subscription.
- A server with a public
https://URL to run the integration service.
Member emails
HubSpot matches contacts by email, so check how your Network exposes member emails before you start:- Webhook payloads return an empty email when the member hasn’t consented to commercial email, and a masked email (
a***@***.***) unless your Network’s plan includes member-email visibility. - The Mighty API returns plain email addresses only to a Host token that carries the
read:userinfoscope, on a plan that includes member-email visibility. Otherwise, addresses come back obfuscated.
isUsableEmail check.
Step 1: Set up HubSpot
- In HubSpot, create a private app for the integration.
- On the Scopes tab, add
crm.objects.contacts.readandcrm.objects.contacts.write. - Create the app and copy its access token. Store it on your server as
HUBSPOT_TOKEN. - Create custom contact properties for the Mighty data you want to keep. This guide uses:
Step 2: Create an OAuth application
- In your Network, go to Network Admin > Integrations > OAuth Applications and click New OAuth Application.
- Choose client type Confidential. Your integration runs on a server, so it can keep a client secret. See Backend web apps.
- Register your service’s callback URL as the redirect URI, for example
https://hubspot-sync.example.com/oauth/callback. - Select these scopes:
- Save the application and store the Client ID and Client Secret on your server as
MIGHTY_CLIENT_IDandMIGHTY_CLIENT_SECRET.
Because this application requests
host: scopes, only Hosts of the Network can complete the sign-in. That’s what you want here: a Host connects the integration once, and it acts with that Host’s permissions.Step 3: Connect the Network and call the API
A Host connects the integration by going through the Authorization Code flow once. Your service redirects them tohttps://YOUR_SUBDOMAIN.mn.co/oauth/authorize with the scopes from Step 2, validates state on the callback, and exchanges the code for an access token and a refresh token. Store the refresh token encrypted on your server.
Access tokens expire after one hour, so wrap every Mighty API call in a helper that refreshes the token when it needs to:
mighty.js
Step 4: Write contacts to HubSpot
Add a helper that creates or updates HubSpot contacts, matched on email. Sending contacts in batches of up to 100 keeps you well inside HubSpot’s API limits.hubspot.js
Step 5: Register a webhook
Now tell your Network to send member events to your service. Generate a long random secret, store it asMIGHTY_WEBHOOK_SECRET, and register the webhook with createWebhookCallback. Mighty sends the secret as a Bearer token on every delivery so your service can verify it.
register-webhook.js
updateWebhookCallback. To list the webhooks already registered on your Network, query network { webhookCallbacks { nodes { id url includedEvents disabled } } }.
Step 6: Handle webhook deliveries
Each delivery is an HTTPPOST with a JSON body:
event_type is the event name followed by Hook, such as MemberJoinedHook or MemberPurchasedHook. Payload fields use snake_case.
This endpoint verifies the secret, acknowledges the delivery right away, and then writes to HubSpot:
server.js
appendTag to fit your CRM. For example, read the contact’s current mighty_tags value from HubSpot and append the new tag, or add the contact to a HubSpot list named after the tag.
Before you rely on the payload shape for a new event, check it in the webhook reference. Webhooks registered through the Mighty API and through Network Admin use the same delivery format.
Step 7: Backfill existing members
Webhooks only cover events from now on. To load everyone who joined before you registered the webhook, page through the member roster once and send each page to HubSpot:backfill.js
RESOURCE_ID for a backfill. Other sort keys, such as the default LAST_VISIT, can change while you page, so a member can be skipped or returned twice. Always page from pageInfo.endCursor until hasNextPage is false. See Query cost limits for how page size affects cost.
Step 8: Send HubSpot changes to Mighty
Now go the other way. When something happens in HubSpot, like a deal closing or a contact joining a list, a HubSpot workflow calls your service and your service updates the Network.Set up the HubSpot workflow
- In HubSpot, create a contact-based workflow with the enrollment trigger you want, such as Lifecycle stage is Customer.
- Add a Send a webhook action with method
POSTand the URLhttps://hubspot-sync.example.com/webhooks/hubspot. - Include the contact’s Email, First name, and Last name in the request body.
- Add authentication so your service can verify the request. Send a long random secret in an
X-Sync-Secretheader and store it asHUBSPOT_WEBHOOK_SECRET. If you use HubSpot’s request signature instead, verify that in place of the header check below.
Tag the member, or invite them if they’re new
Your service looks up the contact in your Network by email. If they’re already a member, it adds a tag. If not, it sends them an invite.server.js
createInvites can also invite people to a specific Space with spaceId, or to a paid or free plan with planId. For example, you could invite a contact straight to your premium plan when their HubSpot deal closes.
memberByEmail returns null both when no member has that email and when your Host token can’t see the member’s email, for example because of the member’s email-sharing consent. It’s also rate limited for lookups that don’t find anyone. If an invite is ignoredRecipients, the person is already a member or already has a pending invite.Run it in production
- Respond fast. Return a
2xxresponse before doing any HubSpot work. Deliveries time out after 10 seconds and are retried with backoff for about two hours. If a webhook has 5 consecutive failed deliveries and the first failure is at least 3 days old, it’s automatically disabled. Once disabled, no more deliveries are attempted and itsdisabledfield istrue. To re-enable it, fix your endpoint, then callupdateWebhookCallback. - Ignore duplicates. Retries can deliver the same event more than once. Store each
event_idyou’ve processed in a database, not in memory. - Don’t lose failed events. Your endpoint acknowledges each delivery before it writes to HubSpot, so Mighty doesn’t retry an event that fails afterward. Put deliveries on a durable queue, or store failed events, and replay them once HubSpot is reachable again.
- Check every GraphQL response. The Mighty API returns HTTP
200for most errors, and mutations also return anerrorsarray in their payload. See Errors. - Handle a disconnected Host. If a token refresh returns
invalid_grant, the Host revoked access, changed their password, or the application was deleted. Alert your team so a Host can reconnect the integration. - Watch your quotas. Mighty API usage counts against your Network’s quota (see Rate Limits), and HubSpot enforces its own limits. Batch writes where you can.
- Track schema changes. Subscribe to the changelog so you hear about new fields and deprecations before they affect your integration.
Next steps
Authentication
Implement the OAuth flow the Host uses to connect the integration.
GraphQL Schema Explorer
Explore member, tag, and invite fields to sync more data to HubSpot.
OAuth Client Architectures
Keep tokens on your server and avoid the token proxy anti-pattern.
Webhook reference
See every webhook event and its payload.