Connect Facebook Pages

Mint a Facebook connect link, match the owner's Pages to your locations, confirm or hand-pick the links, and disconnect the account when a client leaves.

A connected Facebook account is what lets a location publish and report on Facebook. Once a Page is linked, posts can target FACEBOOK in postSites, the Facebook analytics endpoint returns Page metrics instead of null, the Page is added as a review source so its reviews arrive with the rest, and the Facebook row in the location's premium listings leaves REQUIRING_ACTION.

The flow is the same as Google: mint a link, let the owner consent, match, confirm. Where a value differs for Facebook it is called out.

The body carries only your two redirect URLs. The link is scoped to the account that owns the key and is valid for 24 hours.

Connect link
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connect-facebook \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "successUrl": "https://app.example.com/connect/facebook/success",    "errorUrl": "https://app.example.com/connect/facebook/error"  }}'
JSON
{  "data": {    "bulkConnectLinkForFacebook": {      "success": true,      "url": "https://claim.verifymybiz.com/locations/redirect_oauth_bulk/facebook?onboarding=false&platform=local&token=bfac8e06-...",      "errors": null    }  }}

Redirect the owner to url. They accept Facebook's terms, grant the Page permissions, and land on your successUrl.

2. List connected accounts after OAuth returns

Filter by publisher=FacebookAccount. This is an offset page: records[] plus pageInfo.totalRecords, paged with page and perPage.

List accounts
curl "https://listingsapi.com/api/v4/connected-accounts?publisher=FacebookAccount&page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectedAccountsInfo": {      "pageInfo": { "hasNextPage": false, "totalRecords": 1 },      "records": [        {          "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d",          "connectedAccountType": "FacebookAccount",          "status": "CONNECTED",          "requestMatchesStatus": "MATCH_COMPLETED",          "connectedLocationsCount": 0        }      ]    }  }}

Keep the connectedAccountId. status is CONNECTED, MATCH_IN_PROGRESS, or CONNECTIVITY_ISSUE; anything but CONNECTED means the owner has to re-authorize before the next steps will work.

3. Trigger matching and wait for it to finish

Matching pulls the Pages the account can reach and pairs each with one of your locations. It runs in the background, so poll the account's details until requestMatchesStatus is MATCH_COMPLETED. Reading suggestions before then returns an empty records array that looks like "no matches".

Trigger and poll
curl -X POST https://listingsapi.com/api/v4/connected-accounts/trigger-matches \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "connectedAccountIds": ["d2397854-52c2-41d7-95f1-b90cba16498d"] } }' # then, every 15 seconds until requestMatchesStatus is MATCH_COMPLETEDcurl https://listingsapi.com/api/v4/connected-accounts/d2397854-52c2-41d7-95f1-b90cba16498d/details \-H "Authorization: API $LISTINGSAPI_KEY"

The details record sits at data.connectedAccountDetails.details. MATCH_COMPLETED means the matcher finished; nothing is linked until you confirm, so connectedLocationsCount stays 0 for now.

4. Review and confirm suggestions

Each record pairs your location (locationInfo, locationId) with a Page (suggestedLocationInfo). For a Facebook account accountType is FB rather than GMB, and that changes the id you send to confirm.

Suggestions
curl "https://listingsapi.com/api/v4/connected-accounts/d2397854-52c2-41d7-95f1-b90cba16498d/connection-suggestions?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"

A suggestion has no id. Build one as the base64 of <MatchRecordType>:<matchedDataDatabaseId>, picking the type from accountType. The reference only shows a Google example, which decodes to GmbLocationMatchedData:...; the type differs per publisher. For Facebook it is FbLocationMatchedData, so FB with 0d5e306f-0da0-46e3-929f-fd3c67ccd8cc encodes as RmJMb2NhdGlvbk1hdGNoZWREYXRhOjBkNWUzMDZmLTBkYTAtNDZlMy05MjlmLWZkM2M2N2NjZDhjYw==.

accountTypeMatch-record type
GMBGmbLocationMatchedData
FBFbLocationMatchedData
APPLEAppleLocationMatchedData
Confirm matches
# base64 of FbLocationMatchedData:0d5e306f-0da0-46e3-929f-fd3c67ccd8cccurl -X POST https://listingsapi.com/api/v4/connected-accounts/confirm-matches \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "matchRecordIds": ["RmJMb2NhdGlvbk1hdGNoZWREYXRhOjBkNWUzMDZmLTBkYTAtNDZlMy05MjlmLWZkM2M2N2NjZDhjYw=="] } }'

The response is data.confirmConnectMatches with success and failedIds, the decoded database ids that could not be confirmed. An id built with the wrong type returns 200 with success: false and no failedIds, so always check success.

When the matcher is unsure, or a Page was created after matching ran, list the Pages the account can see and link one directly. connectedAccountId goes in the JSON body of the listings call; as a query parameter it is ignored and you get the first connected account's listings.

Pick and link
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connected-account-listings \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d", "locationInfo": "Lincoln" }' curl -X POST https://listingsapi.com/api/v4/connected-accounts/connect-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d",    "connectedAccountListingId": "<id from the listings response>"  }}'

Each listing record carries id, locationName, address, and liveLink. Its id is the connectedAccountListingId that connect-listing takes; the field is not called listingId. A failed link returns success: false with a message such as Listing record not found.

6. Disconnect the account when a client leaves

Disconnecting is all or nothing: every Page linked through the account stops syncing and Facebook interactions stop arriving. To detach one location while keeping the account, use disconnect-listing instead.

Disconnect
curl -X POST https://listingsapi.com/api/v4/connected-accounts/disconnect-facebook \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d" } }'

The response is data.fbBulkDisconnect with success. It is true even for an unknown connectedAccountId, so it means "processed", not "a live connection was removed". List connected accounts again if you need certainty.

7. What happens next

A connection.location_connected event with data.platform: "facebook" fires for each linked location, and connection.location_disconnected fires when you unlink. If Facebook invalidates the grant you receive connection.reauth_required: mint a new link (step 1) and ask the owner to consent again with every permission. Once linked, the Facebook row in the location's premium listings moves to SYNCED, postSites: ["FACEBOOK"] becomes a valid target, and the Facebook analytics endpoint starts returning data.

Next steps