Connected accounts

Every Connected accounts endpoint with a cURL, Python and Node sample: connect Google and Facebook, list accounts, match and link listings, folders, GMB creation, disconnects.

A connected account is an OAuth grant from a Google Business Profile or Facebook Pages owner that lets the API read and manage the listings that account can reach. The resource covers three jobs: minting the OAuth links, matching or linking the account's listings to your locations, and tearing the connection down again. The two GET list and detail reads work with a Read key; every POST, including the read-only listings fetch, needs a Write key, and a Read key on a write returns HTTP 400 with SY90016.

Every sample below assumes a client built once, the way the first sample shows, and reads LISTINGSAPI_KEY from the environment. Ids are the connectedAccountId UUID from the list endpoint and the base64 location id (TG9jYXRpb246MTgwMDI4OQ==); never URL-encode either.

Endpoints at a glance

MethodPathWhat it doesReference
POST/connected-accounts/connect-googleMint a 24-hour bulk connect link for a Google account.Connect a Google account
POST/connected-accounts/connect-facebookMint a 24-hour bulk connect link for a Facebook account.Connect a Facebook account
POST/locations/oauth_connect_urlMint a single-use connect link tied to one location.OAuth connect URL for one location
GET/connected-accountsList connected accounts with health and linked counts.List connected accounts
GET/connected-accounts/{connectedAccountId}/detailsRead one account, including match-job status.Get connected account details
POST/connected-accounts/connected-account-listingsList the publisher listings an account can reach.Fetch listings of a connected account
POST/connected-accounts/trigger-matchesQueue the fetch-and-match job for one or more accounts.Trigger location matches
GET/connected-accounts/{connectedAccountId}/connection-suggestionsRead the suggested location-to-listing pairings.List connection suggestions
POST/connected-accounts/confirm-matchesAccept suggestions and create the live links.Confirm connection matches
POST/connected-accounts/connect-listingLink one chosen listing to one location.Connect a listing to a location
POST/connected-accounts/disconnect-listingUnlink one location from one publisher.Disconnect a listing from a location
POST/connected-accounts/create-location-from-listingCreate a new location from a publisher listing.Create a location from a listing
GET/connected-accounts/{connectedAccountId}/foldersList the Google account groups (folders).List GMB folders
POST/locations/create/gmb-listingCreate a brand-new Google Business Profile for a location.Create a GMB listing
POST/connected-accounts/disconnect-googleDisconnect a whole Google account.Disconnect a Google account
POST/connected-accounts/disconnect-facebookDisconnect a whole Facebook account.Disconnect a Facebook account
POST/locations/oauth-disconnectDisconnect one location from a publisher (same operation as disconnect-listing).Disconnect one location from a publisher

POST /connected-accounts/connect-google

Returns a short-lived OAuth URL. Redirect the account owner to it; Google returns them to your successUrl or errorUrl. The link is scoped to the account that owns the API key, so the body carries only your two redirects. Re-issuing a link for an account whose grant expired refreshes the existing connection rather than duplicating it.

NameInRequiredNotes
inputbodyyesWrapper object; the whole body sits under it.
input.successUrlbodyyesAbsolute https URL you control. Reached after consent.
input.errorUrlbodyyesAbsolute https URL you control. Reached on cancel or failure.
Connect Google
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connect-google \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "successUrl": "https://app.example.com/connect/google/success",    "errorUrl": "https://app.example.com/connect/google/error"  }}'
JSON
{  "data": {    "bulkConnectLinkForGoogle": {      "success": true,      "url": "https://claim.verifymybiz.com/locations/redirect_oauth_bulk/google_oauth2?onboarding=false&platform=local&token=9009dc92-...",      "errors": null    }  }}

The link is valid for 24 hours. errors is populated only when generation fails, so check that url is non-null. A flat body, or one carrying an accountId, is rejected with HTTP 400.

POST /connected-accounts/connect-facebook

The Facebook counterpart, with the same body. During the flow the owner accepts Facebook's terms and grants the page-management permissions the API needs; if they skip a permission the connection cannot sync, so re-issue the link and have them consent again.

NameInRequiredNotes
inputbodyyesWrapper object.
input.successUrlbodyyesAbsolute https URL you control.
input.errorUrlbodyyesAbsolute https URL you control.
Connect Facebook
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    }  }}

The response key is bulkConnectLinkForFacebook; otherwise read it exactly like the Google link. Once the owner finishes, the account appears in the list endpoint as a FacebookAccount.

POST /locations/oauth_connect_url

Use this for a "Connect Google" button on a single location's page. The link is tied to the location you name, so no matching step follows: when the owner consents, the credentials attach to that location directly. Both bulk links above connect a whole account instead.

NameInRequiredNotes
inputbodyyesWrapper object.
input.locationIdbodyyesBase64 location id, or the raw numeric id.
input.sitebodyyesGOOGLE, FACEBOOK, or APPLE.
input.successUrlbodyyesAbsolute URL reached after the grant.
input.errorUrlbodyyesAbsolute URL reached on cancel or failure.
Single-location link
curl -X POST https://listingsapi.com/api/v4/locations/oauth_connect_url \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "site": "GOOGLE",    "successUrl": "https://app.example.com/locations/1800289/connected",    "errorUrl": "https://app.example.com/locations/1800289/connect-failed"  }}'
JSON
{  "data": {    "createConnectUrl": {      "success": true,      "url": "https://accounts.google.com/o/oauth2/auth?client_id=...&state=8f3c1d92-4a7e-4d0b-9c31-6b2f7ae51c04",      "errors": null    }  }}

The link is single-use, so mint a fresh one per attempt rather than caching it. A relative or unparseable redirect URL comes back as success: true with a null url, so check url and not just success. A key that may not touch this location gets a 403 with SY90003. The SDKs uppercase site for you.

List connected accounts

GET /connected-accounts

Returns every account authorized against your API account, with connection health and how many locations each one links. This is an offset page: records[] plus pageInfo.totalRecords, paged with flat page and perPage query parameters. Ordering is fixed to account email ascending.

NameInRequiredNotes
pagequeryno1-based page number. Default 1.
perPagequerynoRecords per page. Default 20.
publisherquerynoGoogleAccount, FacebookAccount, AppleAccount, YelpAccount, TripadvisorAccount, LinkedinAccount, PinterestAccount, or TwitterAccount.
statusquerynoConnected, NotConnected, or ConnectionIssue. Mixed case.
List accounts
curl "https://listingsapi.com/api/v4/connected-accounts?publisher=GoogleAccount&status=Connected&page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectedAccountsInfo": {      "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "totalPages": 1, "totalRecords": 1 },      "records": [        {          "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",          "connectedAccountType": "GoogleAccount",          "email": "owner@brightsmile-dental.com",          "status": "CONNECTED",          "connectivityIssue": null,          "connectedLocationsCount": 0,          "requestMatchesStatus": "MATCH_COMPLETED",          "lastFetchMatchesRequestedAt": "2026-07-06 21:43:07 UTC"        }      ]    }  }}

Pick the record whose email is the owner who consented and keep its connectedAccountId; every later call takes it. Anything other than the four query parameters is ignored rather than rejected, so a JSON pageInfo silently returns page 1.

Record statusMeaning
CONNECTEDCredentials are valid. Safe to trigger matching or publish.
MATCH_IN_PROGRESSA match run is queued or running.
CONNECTIVITY_ISSUEThe grant expired. connectivityIssue says why; re-issue the connect link.

The status filter and the record's status field do not share a vocabulary. Feeding CONNECTED back in as the filter is an invalid enum and returns a 400.

Get one account's details

GET /connected-accounts/{connectedAccountId}/details

Returns the same fields as one list record, scoped to one account. Use it to poll requestMatchesStatus after triggering matches, or to check status and connectivityIssue before pushing an update through the account.

NameInRequiredNotes
connectedAccountIdpathyesUUID from the list endpoint.
Account details
curl https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/details \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectedAccountDetails": {      "details": {        "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",        "connectedAccountType": "GoogleAccount",        "status": "CONNECTED",        "connectivityIssue": null,        "connectedLocationsCount": 0,        "requestMatchesStatus": "MATCH_COMPLETED"      }    }  }}

The record sits one level down at data.connectedAccountDetails.details. requestMatchesStatus moves from MATCH_IN_PROGRESS to MATCH_COMPLETED when suggestions are ready. Completed means the matcher finished, not that anything is linked: connectedLocationsCount stays 0 until you confirm or connect a listing.

Fetch the listings an account can reach

POST /connected-accounts/connected-account-listings

Lists every Google Business Profile or Facebook listing the account has access to, whether or not it is linked to one of your locations. Each record's id is the connectedAccountListingId that connect-listing and create-location-from-listing take. This is a POST that only reads, and it returns an offset page: records[] plus pageInfo, paged with flat page and perPage keys in the body.

NameInRequiredNotes
connectedAccountIdbodyyesUUID of the account whose listings to fetch. Not wrapped in input.
pagebodynoPage number. Default 1.
perPagebodynoRecords per page. Default 500, which is also the maximum.
locationInfobodynoFree-text search across name, address, locality, postal code, store code, and phone.
Account listings
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": "4f712c17-4f95-42dd-90f4-97171a2e67b5", "perPage": 50, "locationInfo": "William St" }'
JSON
{  "data": {    "connectedAccountListings": {      "pageInfo": { "hasNextPage": false, "totalPages": 1, "totalRecords": 60 },      "records": [        {          "id": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA==",          "accountTypeName": "Google",          "locationName": "Trial",          "address": "123 William St, NY 10038, Manhattan, US",          "phone": "(718) 667-7787",          "liveLink": null        }      ]    }  }}

Walk the set with pageInfo.hasNextPage and pageInfo.totalPages. The SDKs put connectedAccountId in the body for you, so the trap above only bites hand-written REST calls.

Trigger matching

POST /connected-accounts/trigger-matches

Queues the job that pulls every profile the named accounts can reach and pairs each with one of your locations. Matching considers every active, unarchived location that is not already connected. It writes suggestions only; nothing is linked until you confirm.

NameInRequiredNotes
inputbodyyesWrapper object.
input.connectedAccountIdsbodyyesArray of account UUIDs from the list endpoint.
Trigger matches
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": ["4f712c17-4f95-42dd-90f4-97171a2e67b5"] } }'
JSON
{  "data": {    "connectedAccountsTriggerMatches": {      "success": true,      "failedIds": null    }  }}

success: true means the job was queued, not that matching finished. Any account that could not be queued is listed in failedIds and success is false. Poll the details endpoint until requestMatchesStatus is MATCH_COMPLETED before reading suggestions; every 15 seconds with a bounded loop keeps a Launch plan inside its 10 requests a minute.

Read connection suggestions

GET /connected-accounts/{connectedAccountId}/connection-suggestions

Returns the pairings the matcher proposed: your location on one side (locationInfo, with locationId as its databaseId) and the publisher listing on the other (suggestedLocationInfo). This is an offset page paged with flat page and perPage query parameters; ordering is fixed to location info ascending.

NameInRequiredNotes
connectedAccountIdpathyesUUID of the account.
pagequeryno1-based page number. Default 1.
perPagequerynoRecords per page. Default 20.
Suggestions
curl "https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/connection-suggestions?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectionSuggestionsForAccount": {      "pageInfo": { "hasNextPage": false, "totalPages": 1, "totalRecords": 2 },      "records": [        {          "accountType": "GMB",          "matchedDataDatabaseId": "0d5e306f-0da0-46e3-929f-fd3c67ccd8cc",          "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",          "locationId": "73415",          "locationInfo": { "name": "My Business", "city": "Lincoln", "stateIso": "NE" },          "suggestedLocationInfo": { "locationInfo": { "name": "My Business", "city": "Lincoln" } }        }      ]    }  }}

A suggestion has no id. Keep matchedDataDatabaseId and accountType together; confirm-matches needs both to build its id. Read too early, before MATCH_COMPLETED, the endpoint returns records: [] with totalRecords: 0, which looks exactly like "nothing matched".

accountTypePublisherMatch-record type
GMBGoogle Business ProfileGmbLocationMatchedData
FBFacebook PagesFbLocationMatchedData
APPLEApple Business ConnectAppleLocationMatchedData

Confirm matches

POST /connected-accounts/confirm-matches

Accepts the suggestions you approve and creates the live links. Each id is the base64 of <MatchRecordType>:<matchedDataDatabaseId>, with the type chosen from the table above. The account is inferred from the records, so there is no connectedAccountId field; an unknown field inside input is rejected with a 400.

NameInRequiredNotes
inputbodyyesWrapper object. Only matchRecordIds is declared.
input.matchRecordIdsbodyyesArray of base64 match-record ids. At least one.
Confirm matches
# base64 of GmbLocationMatchedData: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": ["R21iTG9jYXRpb25NYXRjaGVkRGF0YTowZDVlMzA2Zi0wZGEwLTQ2ZTMtOTI5Zi1mZDNjNjdjY2Q4Y2M="] } }'
JSON
{  "data": {    "confirmConnectMatches": {      "success": true,      "failedIds": null    }  }}

failedIds holds the decoded matchedDataDatabaseId values that could not be confirmed, such as a record already consumed or a location archived since matching, so match them back against the suggestion records. Unsent suggestions are left untouched. Confirming links the location to the listing; it does not push data to the publisher on its own.

Connect one listing to a location

POST /connected-accounts/connect-listing

Links a single listing you have already chosen to a single location, with no suggestion or confirm step. Use it when matching is ambiguous, for example two nearby storefronts with similar names, and an operator picks the right one from the account's listings.

NameInRequiredNotes
inputbodyyesWrapper object.
input.locationIdbodyyesBase64 location id.
input.connectedAccountIdbodyyesUUID of the account that owns the listing.
input.connectedAccountListingIdbodyyesThe id of a record from the account listings endpoint. Not listingId.
Connect listing
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": "4f712c17-4f95-42dd-90f4-97171a2e67b5",    "connectedAccountListingId": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA=="  }}'
JSON
{  "data": {    "connectListing": {      "success": true,      "message": null    }  }}

A failed link returns success: false with a non-null message, for example Listing record not found when the listing id does not resolve, or a note that the listing is already connected to another location. In both SDKs this method lives on the listings resource, not on connected accounts.

Disconnect one listing from a location

POST /connected-accounts/disconnect-listing

Severs the link between one location and one publisher. The location and its data stay; only outbound sync to that publisher stops. This is not a bulk endpoint, so loop over locations. To re-point a store to a different Google account, disconnect here first, then match or connect on the new account.

NameInRequiredNotes
inputbodyyesWrapper object.
input.locationIdbodyyesBase64 id of the one location.
input.sitebodyone ofGOOGLE, FACEBOOK, or APPLE. Required unless providerId is sent.
input.providerIdbodyone ofThe publisher's own account identifier, instead of site.
Disconnect listing
curl -X POST https://listingsapi.com/api/v4/connected-accounts/disconnect-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "locationId": "TG9jYXRpb246MTgwMDI4OQ==", "site": "GOOGLE" } }'
JSON
{  "data": {    "disconnectConnectedAccountsLocations": {      "clientMutationId": null,      "success": true,      "errors": null    }  }}

Sending neither site nor providerId returns SY10056. A location with no active connection for that site returns SY10057 rather than a silent success, so success: true really does mean a link was removed. The SDKs take site only and uppercase it.

Create a location from a listing

POST /connected-accounts/create-location-from-listing

Matching only pairs listings with locations you already have. For a listing with no location, this creates one from the publisher's data and links it back to the listing at once. Google imports name, address, coordinates, phone, website, description, regular and special hours, categories, opening date, store code, and timezone, plus payment methods and social links derived from the listing's Google attributes. Photos and videos are not imported, and media on the Google profile is never modified or removed. Facebook imports name, location, hours, categories, description, and contact info.

For a Google import the data is not resubmitted to Google, so its listing stays at IN_PROGRESS until your first location update publishes to it. Every other publisher is submitted normally, and this endpoint takes no site scope, so the location is created against your account's full publisher set. Narrow it with enabledSiteIds straight after creation, and send that update immediately: order items for the other publishers are generated shortly after creation, and any already generated are not withdrawn by the update.

Neither SDK wraps this endpoint yet, so the Python and Node samples call REST with the same header.

NameInRequiredNotes
inputbodyyesWrapper object.
input.connectedAccountIdbodyyesUUID of the account that owns the listing.
input.connectedAccountListingIdbodyyesThe id of a record from the account listings endpoint. Not listingId.
Create from listing
curl -X POST https://listingsapi.com/api/v4/connected-accounts/create-location-from-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",    "connectedAccountListingId": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA=="  }}'
JSON
{  "data": {    "createLocationFromConnectedAccountListing": {      "success": true,      "locationId": 88277,      "errors": null    }  }}

locationId is the new location's plain databaseId. On failure success is false, locationId is null, and errors carries a coded reason such as SY81067 (the listing id did not resolve); other causes are a listing already linked to another location, or an account whose credentials expired. Once created, manage the location like any other.

List a Google account's folders

GET /connected-accounts/{connectedAccountId}/folders

Returns the Google Business Profile account groups (folders) the connected Google account can access. Use it before creating a GMB listing so the new profile lands in the group the owner expects. The response is a plain array under getFoldersUnderGoogleAccount, not a page. The path is only valid for GoogleAccount connections.

NameInRequiredNotes
connectedAccountIdpathyesUUID of a Google-type account.
Folders
curl https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/folders \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "getFoldersUnderGoogleAccount": [      { "folderId": "accounts/104890024806530350198", "folderName": "Bright Smile Dental", "locationCount": null }    ]  }}

Use folderId verbatim; it is the accounts/{id} string, not a number. locationCount may be null when Google does not report it, so treat it as optional.

Create a Google Business Profile for a location

POST /locations/create/gmb-listing

Creates a brand-new Google listing for a location that has none, under a connected Google account, and optionally inside a folder. Contrast with connect-listing, which links a listing that already exists. The location must already carry a name, address, and phone, and only one Google listing can exist per location.

NameInRequiredNotes
inputbodyyesWrapper object.
input.locationIdbodyyesBase64 location id.
input.connectedAccountIdbodyyesUUID of the Google account to create under.
input.folderIdbodynoaccounts/{id} string from the folders endpoint. Omit for the account root.
Create GMB listing
curl -X POST https://listingsapi.com/api/v4/locations/create/gmb-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",    "folderId": "accounts/104890024806530350198"  }}'
JSON
{  "data": {    "createGmbListingForLocation": {      "clientMutationId": null,      "success": true,      "errors": null    }  }}

Creation is asynchronous: success: true means the request was accepted, and Google reviews new profiles before they publish. When success is false, errors says why: missing required fields, an existing Google listing, an archived location, or an inactive account.

Disconnect a whole Google account

POST /connected-accounts/disconnect-google

Tears down the connection for the entire account: every location linked through it stops syncing. There is no locationIds field; to detach one location and keep the account, use disconnect-listing instead. Use this when a client leaves, or when a broken grant will not clear and you want to start over with a fresh connect link.

NameInRequiredNotes
inputbodyyesWrapper object.
input.connectedAccountIdbodyyesUUID of the Google account. The whole account is disconnected.
Disconnect Google
curl -X POST https://listingsapi.com/api/v4/connected-accounts/disconnect-google \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d" } }'
JSON
{  "data": {    "gmbBulkDisconnect": {      "success": true    }  }}

success: true is returned even for an unknown connectedAccountId, so it means "the request was processed", not "a live connection was removed". List connected accounts again if you need certainty.

Disconnect a whole Facebook account

POST /connected-accounts/disconnect-facebook

The Facebook counterpart with the same body. Pages linked through the account stop syncing and Facebook interactions stop appearing.

NameInRequiredNotes
inputbodyyesWrapper object.
input.connectedAccountIdbodyyesUUID of the Facebook account. The whole account is disconnected.
Disconnect Facebook
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" } }'
JSON
{  "data": {    "fbBulkDisconnect": {      "success": true    }  }}

The response key is fbBulkDisconnect. As with Google, success: true for an unknown id means processed, not removed.

Disconnect one location from a publisher

POST /locations/oauth-disconnect

The disconnect half of the per-location OAuth flow. It is the same operation as disconnect-listing behind a second path: identical input body, same upstream mutation, same disconnectConnectedAccountsLocations response key. Pick whichever path reads better in your integration.

NameInRequiredNotes
inputbodyyesWrapper object.
input.locationIdbodyyesBase64 id of the one location.
input.sitebodyone ofGOOGLE, FACEBOOK, or APPLE. Required unless providerId is sent.
input.providerIdbodyone ofThe publisher's own account identifier, instead of site.
OAuth disconnect
curl -X POST https://listingsapi.com/api/v4/locations/oauth-disconnect \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "locationId": "TG9jYXRpb246MTgwMDI4OQ==", "site": "GOOGLE" } }'
JSON
{  "data": {    "disconnectConnectedAccountsLocations": {      "clientMutationId": null,      "success": true,      "errors": null    }  }}

The same SY10056 and SY10057 rules apply, and a key that may not touch this location gets a 403 with SY90003. Disconnecting leaves the location and its data intact; only outbound sync to that publisher stops. Send the owner back through the connect URL, or run matching and connect-listing, to attach the correct listing afterwards.

Errors you will see

Malformed requests and bad keys return a 4xx with a top-level errors[] whose message starts with the code. Mutations can also answer 200 with success: false and the reason inside data.<operation>, so check the body of every write. The full list is at Error codes.

Code or statusMeaningFix
SY90016 (400)A Read key was used on a POST.Use a Write key.
SY90003 (403)The key may not connect or disconnect this location.Use a key with access to the location.
SY10056 (200)Disconnect sent neither site nor providerId.Send one of them.
SY10057 (200)The location has no active connection for that site.Nothing to remove; check the location's listings.
SY81067 (200)connectedAccountListingId did not resolve on create-from-listing.Re-fetch the account listings and use a record's id.
400, Variable "$input" ... was not providedThe body was not wrapped in input, or a required field was missing.Nest the body under input; use connectedAccountListingId, not listingId.
400, invalid enumA record's CONNECTED status was fed back as the list status filter.Filter with Connected, NotConnected, or ConnectionIssue.
429Rate limit exceeded.Wait for Retry-After; see Rate limits.

Next steps