Documentation

Facebook

Connect Facebook for page posting, ads management, lead form ingestion, and social activity sync.

The Facebook integration covers four surfaces: posting to pages, running ads through Marketing API, ingesting leads from Lead Ads, and syncing post engagement back into the CRM. Once connected, the same OAuth grant covers Instagram (which is Facebook-owned and shares the Graph API).

Connect Facebook

Facebook uses OAuth 2.0 with system-user-style long-lived tokens. The flow follows the universal OAuth flow; vendor segment is facebook.

const { authUrl } = await fetch('/api/upstream/call/facebook-provider/get-auth-url', {
  method: 'POST',
  headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` },
  body: JSON.stringify({
    scopes: [
      'pages_manage_posts',
      'pages_read_engagement',
      'pages_manage_engagement',
      'pages_show_list',
      'business_management',
      'ads_management',
      'leads_retrieval',
      'instagram_basic',
      'instagram_content_publish',
    ],
    returnUrl: 'https://admin.example/integrations',
  }),
}).then(r => r.json());

window.location = authUrl;

After consent, Facebook returns the user to AppEngine's callback at /connect/oauth2callback/facebook. The connector exchanges the code for a short-lived token, then exchanges that for a long-lived (60-day) token, fetches the page tokens (which don't expire), and stores everything in the integration record.

Page posting

Once connected, the org admin picks which pages to manage. Each page's access token is stored separately:

await fetch('/api/upstream/call/facebook-provider/post-to-page', {
  method: 'POST',
  headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` },
  body: JSON.stringify({
    pageId: '1234567890',
    message: 'Spring sale starts now! 20% off everything.',
    link: 'https://shop.example/spring',
    image: 'https://cdn.../spring-sale.jpg',
  }),
});

For Instagram posts, swap post-to-page for post-to-instagram — the call accepts a media URL and caption and goes through the Instagram Graph API.

The Marketing module's campaigns push to Facebook through this connector when channels includes facebook.

Ads

Facebook ads management lives in the Ads module. The connector exposes campaign create/launch/pause through POST /upstream/call/facebook-provider/... operations, which the Ads module wraps. Application code rarely calls Upstream for ads directly — use the CRM ads endpoints instead.

Lead Ads

Facebook Lead Ads forms ingest leads via webhook. Subscribe to lead events in the Facebook app's webhook configuration:

https://api.appmint.io/connect/webhook/facebook?orgid=<your-org>

with subscription topic leadgen. When a lead is submitted:

POST/connect/webhook/facebookNo auth

The connector verifies the X-Hub-Signature, fetches the lead details from Graph API (Facebook only sends the lead ID in webhooks), and creates a CRM lead with the form fields mapped. Field mapping is configurable per lead form.

Social sync

Engagement on posts (comments, reactions, shares) flows back into the CRM via the Sync module's Facebook job. The job runs on a schedule, fetches recent activity from each managed page, and writes it to the social activity store. Each comment becomes an inbox conversation; reactions become engagement signals on the contact's profile.

Webhook subscriptions

The connector supports Facebook's three webhook channels:

  • page events — comments, reactions, mentions
  • leadgen events — Lead Ads form submissions
  • messaging events — Messenger/WhatsApp inbound messages (with Business API setup)

All flow through the same /connect/webhook/facebook endpoint. The connector dispatches based on the object field in the payload.

Token expiry and re-auth

Long-lived user tokens expire after 60 days; the connector watches for this and emails the org admin a few days before expiry. Page tokens (derived from a long-lived user token) don't expire on their own — but if the user token expires, the page tokens become invalid by extension.

If a user removes the app from their Facebook account, all tokens revoke immediately. The next call returns a 412-style error and the integration moves to status: "expired". Re-auth via the standard connect flow.

Business Manager

For agency setups where one Facebook account manages multiple businesses, request business_management scope. The connector then exposes the Business Manager API: list businesses, list ad accounts under each, list pages under each. Pick which subset to manage in the platform's admin UI.

Common quirks

  • App review — Facebook requires app review for production scopes (pages_manage_posts, ads_management, leads_retrieval). Until reviewed, only roles in the Facebook app can connect — fine for development, blocking for production.
  • Rate limits — Facebook's per-app and per-page rate limits are aggressive. The connector backs off on 429 responses; bulk operations should batch via the Marketing module rather than calling Upstream in tight loops.
  • Instagram post requirements — Instagram Graph API requires a Business or Creator account linked to a Facebook page; personal Instagram accounts can't post via the API.

Don't store Facebook user PII (the email/phone of the person who connected) outside the integration record. Facebook's terms restrict this; the connector keeps it inside the encrypted credentials blob only.