Skip to main content
This guide walks you through a direct integration between your Mighty Network and ActiveCampaign. When you finish, you’ll have:
  • Real-time sync from Mighty to ActiveCampaign. When a member joins, leaves, updates their profile, gets tagged, buys a plan, cancels, or completes a course, a Mighty webhook calls your server, and your server updates the matching ActiveCampaign contact.
  • A one-time backfill. A script that pages through your existing members with the Mighty API and adds them to ActiveCampaign.
  • Optional sync from ActiveCampaign back to Mighty. An ActiveCampaign automation that tags the member in your Network, for example when a lead finishes a nurture sequence.
If you’d rather not host any code, Zapier can connect Mighty Networks to ActiveCampaign without it. Use this guide when you want full control over the mapping, the ability to backfill existing members, or more volume than a no-code plan allows.

Prerequisites

  • A Mighty Network on the Scale plan or above. You need it for OAuth applications and webhooks.
  • A Network Host account on that Network. You authorize the integration as this Host.
  • An ActiveCampaign account with permission to view API settings.
  • A server that can receive HTTPS requests from the public internet. The examples use Node.js 18 or later with Express, but any language works.

Step 1: Get your ActiveCampaign API credentials

  1. In ActiveCampaign, go to Settings > Developer.
  2. Copy your API URL (for example, https://youraccount.api-us1.com) and your API Key.
  3. Create the list you want members added to, then note its numeric ID. The ID appears in the list’s URL in ActiveCampaign, and GET /api/3/lists returns it too.
Store these as environment variables on your server:
Your ActiveCampaign API key has full access to your account. Keep it on your server. Never put it in client-side code or source control.

Step 2: Create an OAuth application in Mighty

The integration calls the Mighty API as a Network Host, so it needs an OAuth application and a Host’s authorization.
  1. In your Network, go to Network Admin > Integrations > OAuth Applications and click New OAuth Application.
  2. Choose the Confidential client type, because the integration runs on your server.
  3. Register the redirect URI your server handles, for example https://your-server.example.com/oauth/callback.
  4. Select these scopes:
  5. Save the application, then copy the Client ID and Client Secret.
Next, complete the Authorization Code flow once, signed in as a Network Host. Store the resulting refresh token securely on your server. It seeds the token helper in Step 5, which the backfill and the optional reverse sync both use to get access tokens. The webhook you register in Step 4 keeps delivering events on its own.
For more on client types, redirect URIs, and scopes, see OAuth Applications.

Step 3: Build the webhook receiver

Mighty delivers each webhook as an HTTPS POST with a JSON body:
The event_type is the event name with a Hook suffix, for example MemberJoinedHook. When you register the webhook with an API key, Mighty sends that key in an Authorization: Bearer header on every delivery. Check it before you trust the request.

ActiveCampaign helpers

Start with a small module that wraps the ActiveCampaign endpoints the integration uses. It queues requests to stay under ActiveCampaign’s rate limit of 5 requests per second.
activecampaign.js

The webhook endpoint

The server maps each Mighty event to ActiveCampaign updates. Adjust the tag names to fit how you segment contacts.
server.js
Generate a long random value for WEBHOOK_SECRET, for example with openssl rand -hex 32. You register the same value with Mighty in the next step.
Mighty expects a 2xx response within 10 seconds. The example calls ActiveCampaign before it responds, which works for most Networks. But the queue in activecampaign.js spaces requests 200 ms apart, so a handler that makes several ActiveCampaign calls takes about a second to finish. If several events arrive at once, they queue behind each other and can add up to more than 10 seconds. If you expect bursts of activity, such as a large import or a launch, put incoming events on a queue, respond 200 right away, and process the queue in a background worker.

Step 4: Register the webhook

Deploy the receiver, then register its URL with the createWebhookCallback mutation. You can run it in the GraphiQL explorer at https://your-subdomain.mn.co/admin/headless-api/explorer, or send it with any GraphQL client and a Host access token.
Subscribe only to the events your handlers use. If you omit includedEvents, the webhook receives every event type, including posts, comments, and reactions. To confirm it works, join the Network with a test account. A contact tagged Mighty: Member should appear in ActiveCampaign within a minute or so.

Step 5: Backfill existing members

Webhooks only cover changes from now on. To bring over the members you already have, run a one-time script that pages through the roster with the Mighty API. The backfill and the optional reverse sync in Step 6 both need a Mighty access token. Each refresh returns a new refresh token and invalidates the old one, so a shared helper needs to persist the refresh token it gets back and reuse it next time, not the one you started with. This one stores it in a JSON file and caches the access token in memory until shortly before it expires.
mighty.js
Every request to api.mn.co needs a non-empty User-Agent header. Requests without one are blocked and return an HTML page with HTTP 403. Set USER_AGENT to your app’s name and URL.
A JSON file is fine for a single-server script. In production, store the refresh token in a database or secret store instead.
backfill.js
Sorting by RESOURCE_ID returns each member exactly once, even if members visit or join while the script runs. Always page from pageInfo.endCursor. See Query cost limits for how page size affects a query’s cost. Run the backfill after you register the webhook. Otherwise you can miss members who join between the two steps. Running it again is safe, because contact/sync updates existing contacts rather than creating duplicates.

Step 6 (optional): Sync tags from ActiveCampaign back to Mighty

You can also act on your Network from ActiveCampaign. For example, when a lead finishes a nurture sequence, tag them in Mighty so a Mighty automation can welcome them to a Space.
  1. In Mighty, create the tag you want to apply, then find its ID with this query:
  2. Add an endpoint to your server that looks up the member by email and applies the tag. ActiveCampaign’s automation webhooks send form-encoded contact data and can’t set an authorization header, so put a secret in the URL instead.
    server.js
    Failed memberByEmail lookups are rate limited per Network, so point the ActiveCampaign automation only at contacts you know are members, for example ones tagged Mighty: Member, rather than your whole list. Past the limit, the query returns a THROTTLED error.
  3. In ActiveCampaign, open the automation and add a Webhook action pointing at https://your-server.example.com/webhooks/activecampaign?secret=YOUR_AC_WEBHOOK_SECRET.

Troubleshooting

Check your server logs for 401 responses. A 401 means the apiKey you registered doesn’t match WEBHOOK_SECRET. Then check the health of the webhook in Mighty:
A rising consecutiveFailures count means your endpoint is returning errors or timing out. Mighty retries failed deliveries, and pauses a webhook that keeps failing. See Circuit breaker.
The integration skips members whose email it can’t read. A webhook payload leaves out the email of a member who hasn’t agreed to share it, and masks it (a***@***.***) when your plan doesn’t include member email visibility. The GraphQL email field is also obfuscated unless your token has the read:userinfo scope and belongs to a Network Host.
contact/sync matches contacts by email, so a new address creates a new contact. To keep one contact per member, store the ActiveCampaign contact ID against the Mighty member ID (payload.member.id). On MemberUpdatedHook, update that contact’s email through PUT /api/3/contacts/{id}.
ActiveCampaign allows 5 requests per second per account. The queue in activecampaign.js enforces that limit within one process only, and the backfill script runs as a separate process from server.js. If you run the backfill while the webhook receiver is live, each enforces the limit on its own requests, and their combined traffic can still exceed 5 requests per second. Run the backfill during a maintenance window, or add a shared rate limiter, such as one backed by Redis, if you run several servers or workers.

Authentication

Run the OAuth flow and refresh access tokens.

Webhooks

See delivery behavior, retries, and the payload for every event.

Mighty API

Explore the GraphQL endpoint, rate limits, and errors.

OAuth Applications

Configure client types, redirect URIs, and scopes.