List Facebook pages
Lists the Facebook Pages a user can pick from after signing in, so they can choose which Page to connect.
Classic connections require profileId and tempToken from the OAuth redirect. Use X-Connect-Token for headless connections. The dashboard business-login picker instead sends only selectionToken, an encrypted grant valid for ten minutes. This requires the initiating user and current profile access and returns only Page IDs and names. X-Connect-Token cannot authorize business selection.
API key authentication: send your Zernio API key in the Authorization header, prefixed with Bearer.
In: header
Query Parameters
Profile ID from your classic connection flow. Required with tempToken.
Temporary Facebook access token from the classic OAuth callback. Required with profileId unless sent in the X-Temp-Token header.
Set by the Zernio-hosted picker, whose user token stays in an httpOnly cookie. Integrators send tempToken instead.
^[a-f0-9]{32}$Encrypted dashboard business-login grant. Send alone instead of profileId and tempToken. Expires after ten minutes.
Header Parameters
The OAuth user token, in place of the tempToken query parameter. Prefer it: a query string is written to request logs along the way.
Response Body
application/json
application/json
application/json
import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.connect.facebook.listFacebookPages();console.log(data);{ "pages": [ { "id": "123456789", "name": "My Brand Page", "username": "mybrand", "access_token": "EAAxxxxx...", "category": "Brand", "tasks": [ "MANAGE", "CREATE_CONTENT" ] } ], "truncated": false}Connect ads for a platform
Starts connecting a platform's ads account, giving you a dedicated ads connection to manage campaigns without touching posting accounts. Creates a dedicated ads SocialAccount for the specified platform. **Meta business login (opt-in).** Set `loginMode=business` for `facebook` or `instagram` to use Facebook Login for Business and a Business Integration System User token. No posting account is created or required. This mode always returns an authUrl; it returns 503 when the server has no META_ADS_CONFIG_ID. Complete the dialog in a browser. The callback creates or reconnects only the metaads account, preserving its ID and history. Non-empty successful subscription results replace subscribedAdAccountIds to remove stale grants; an empty result leaves routing unchanged. A reconnect is accepted when the new grant shares at least one ad account with the existing connection (its scopedAdAccountIds plus the previous grant, or the ad accounts its old token can read when neither is stored), so re-running the dialog can add, drop or swap ad accounts. A grant with zero overlap is refused before changing the account and redirects with `error=invalid_field_value` and `error_reason=reconnect_mismatch` (disconnect and connect again to switch); when the previous ad accounts cannot be read at all, it redirects with `error=reconnect_required`. On an accepted reconnect the scope is rebuilt from the new grant: `adAccountIds` passed on the re-auth become the scope; otherwise a stored scope keeps its ad accounts that are still granted plus any granted for the first time, and an unscoped connection follows the new grant. Pass `pageId` to select a granted Page for creatives and lead forms. API integrations otherwise reuse the previous Page or sole granted Page. Multiple Pages without a selection return 400 with available Page IDs for API integrations; restart with pageId. Dashboard session logins use the sole current grant automatically or open the existing Facebook Page picker for several grants, including reconnects. Selection completes the Meta Ads connection. Success redirects with connected=metaads, profileId and accountId. Every failure after Meta's dialog redirects to redirect_url (or the dashboard) with `error`, `platform=metaads`, `error_message`, `request_id` and `stage`, plus `is_user_fixable` and `error_reason` when known. `error` is the API error code: `invalid_field_value` with `error_reason` `no_pages_granted` (no Page ticked), `page_not_granted` (pageId not in the grant), `ad_accounts_not_granted` or `reconnect_mismatch` (the grant shares no ad account with the existing connection); `reconnect_required`, `ads_addon_required`, `payment_required` and the profile gates of GET /v1/connect/{platform}; `invalid_state` with `error_reason=state_expired` after the 30-minute window; `connection_failed` when Meta refuses the code (e.g. a replayed callback). A denial in the dialog is `meta_ads_authorization_denied` with the `platform_error*` params. Only a state that cannot be decrypted at all still answers 400 JSON, since it names no redirect_url. Business login reports metadata.tokenType=system-user in GET /v1/accounts. An absent Meta expires_in leaves tokenExpiresAt absent; no personal-token re-exchange occurs. Subsequent classic requests can change the ad-account scope using the business token; force=true (or disconnecting the business connection first) switches the profile to the standard Facebook login; the ads account is then held by the user token. **Same-token platforms (facebook, instagram, linkedin, pinterest).** The ads SocialAccount (metaads, linkedinads, pinterestads) reuses the OAuth token of the parent posting account, but only when an active parent exists and, for facebook and instagram, its stored token carries ads_management and ads_read (linkedin and pinterest need no extra scope). In that case no extra OAuth happens and the response is alreadyConnected: true. When no such parent exists, or the scopes are missing, the endpoint returns an authUrl and a full OAuth round trip is required. When a parent exists but carries no token usable for ad accounts, the call fails with 400 RECONNECT_REQUIRED. Independently of the branch, the call can return 403 ADS_ADDON_REQUIRED without the ads add-on and 402 PAYMENT_REQUIRED when the billing gate is closed. Meta Ads prerequisite: connecting Meta Ads (via facebook or instagram) requires a Facebook Page. Not because the ad account is read through a Page, but because both parent posting accounts are: the facebook flow only offers Pages you manage, and the instagram flow with loginMethod=facebook_login only offers Instagram accounts linked to one of those Pages. Without a Page there is no parent account to inherit a token from. A user who manages no Facebook Page cannot complete this connection, and the facebook flow ends with error=no_facebook_pages. **Separate-token platforms (tiktok, twitter).** Starts the platform-specific marketing API OAuth flow and creates an ads SocialAccount (tiktokads, xads) with its own token. If the ads account already exists, returns alreadyConnected: true. - tiktok: accountId is OPTIONAL. With accountId, the new tiktokads account links to that posting account (parentAccountId set), so Spark Ads + standalone ads using the posting TT_USER identity become available. Without accountId, ads-only mode kicks in: the new tiktokads account has parentAccountId=null and standalone ads use a synthetic CUSTOMIZED_USER ("Brand Identity"); Spark Ads are unavailable because TikTok requires a posting account for them. The Brand Identity is configured separately via PATCH /v1/connect/tiktok-ads (or inline on POST /v1/ads/create via the brandIdentity field). - twitter (X Ads): accountId is REQUIRED. There's no ads-only mode, because tweets need to be authored by a real X user. **Standalone platforms (googleads).** Starts the Google Ads OAuth flow and creates a standalone ads SocialAccount (googleads) with no parent. If the account already exists and has at least one discovered Google Ads customer account, returns alreadyConnected: true. When the existing connection has zero customer accounts (metadata.googleAdsCustomerIds is empty) or is flagged needsReconnection, it returns an authUrl instead; completing it reconnects the same account (same accountId) and re-runs ad account discovery. Discovery includes the client accounts under every manager (MCC) the Google user can reach, and includes Google Ads test accounts, which Google always reports with status CLOSED. When discovery finds no usable customer account, the callback saves nothing and redirects with `error=google_ads_no_ad_accounts`, `platform=googleads` and an `error_message` naming each customer the Google user can reach and why it was left out (for example CUSTOMER_NOT_ENABLED). Sign in with a Google user that has access to the ad account or to its manager account. When the user unticks the Google Ads permission on Google's consent screen, the callback saves nothing and redirects with `error=missing_google_permissions`, `platform=googleads`, `is_user_fixable=true` and `missing_scopes`. An existing connection whose token lacks that permission is flagged needsReconnection, and the health endpoints report "Google Ads permission not granted"; this endpoint then returns an authUrl for it. **Standalone platforms (redditads).** Starts the Reddit Ads OAuth flow (Reddit permissions `adsread`, `adsedit` and `adsconversions`) and creates a standalone ads SocialAccount (redditads) with no parent, separate from any organic `reddit` posting account. It is reached only as `redditads` in the path. If an active Reddit Ads connection already exists on the profile, is not flagged needsReconnection and holds every one of those permissions, returns alreadyConnected: true. Otherwise it returns an authUrl; completing it reconnects the same account (same accountId). A connection authorized without `adsconversions` keeps managing ads, but the health endpoints list an issue asking to reconnect Reddit Ads and allow every permission, the Conversions API answers 403 `reconnect_required`, and this endpoint returns an authUrl for it. Discovery lists every Reddit ad account the Reddit user can reach. When the user unticks `adsread` or `adsedit` on Reddit's consent screen the callback saves nothing and redirects with `error=reddit_ads_scope_not_granted`; when the user reaches no Reddit ad account it redirects with `error=reddit_ads_no_ad_accounts` (both with `platform=redditads`). Without `redirect_url` the browser lands on the Zernio dashboard's ad account picker for the new connection. Ads accounts appear as regular SocialAccount documents with ads platform values (e.g., metaads, tiktokads) in GET /v1/accounts.
Select Facebook page
Connects the Facebook Page the user picked after signing in, completing the Facebook or Meta Ads connection. Complete a classic Facebook Page connection with profileId, pageId, tempToken and userProfile. Use X-Connect-Token for headless connections. The dashboard business-login picker instead sends only selectionToken and pageId to complete a Meta Ads connection. The server verifies the initiating user, profile access, current grants and connection eligibility. The profile, platform token, ad-account scope and return URL come only from the encrypted grant. Business selection requires a session or bearer authentication for the initiating user; X-Connect-Token is not accepted. It returns redirect_url with connected=metaads on success or an eligibility error redirect.