Conecta Google Business Profile e importa tus ubicaciones

Crea un enlace para conectar Google, asocia las fichas de Google del dueño a tus ubicaciones, confirma las asociaciones e importa fichas aún sin ubicación.

Una cuenta de Google conectada permite publicar y generar informes para una ubicación en Google. Hasta que se conecte una, la fila de Google Maps en las fichas premium de una ubicación permanece en REQUIRING_ACTION, no se importan las reseñas de Google, no se pueden publicar publicaciones en GOOGLE y los datos analíticos de Google se devuelven como null. Conectar la cuenta resuelve los cuatro problemas.

El flujo en bloque (pasos 1 a 6) conecta una cuenta de Google completa una sola vez y busca coincidencias entre todas las fichas que posee y tus ubicaciones. El flujo para una sola ubicación (paso 7) conecta una ubicación a la vez: el enlace está vinculado a esa ubicación, por lo que no hay un paso posterior de búsqueda de coincidencias.

El enlace está limitado a la cuenta a la que pertenece la clave de API, por lo que el cuerpo solo contiene tus dos URL de redirección. Dirige al propietario al url devuelto; Google lo redirige a successUrl o errorUrl cuando termina.

Connect link
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://connect.example.com/oauth?token=8f3c1d92-...",      "errors": null    }  }}

El url anterior es un marcador de posición. Dirige al propietario al url devuelto en tu propia respuesta.

El enlace es válido durante 24 horas. Comprueba que url no sea nulo en lugar de confiar únicamente en success. Si las credenciales del propietario caducan más adelante, crea un nuevo enlace de la misma forma: la conexión existente se actualiza, no se duplica.

2. Enumera las cuentas conectadas tras el retorno de OAuth

Cuando el propietario llegue a tu successUrl, enumera las cuentas de Google. Esta página usa paginación por desplazamiento: records[] más pageInfo.totalRecords, con page y perPage para paginar.

List accounts
curl "https://listingsapi.com/api/v4/connected-accounts?publisher=GoogleAccount&page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectedAccountsInfo": {      "pageInfo": { "hasNextPage": false, "totalRecords": 1 },      "records": [        {          "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",          "email": "owner@brightsmile-dental.com",          "status": "CONNECTED",          "requestMatchesStatus": "MATCH_COMPLETED",          "connectedLocationsCount": 0        }      ]    }  }}

Selecciona el registro cuyo email sea el propietario que acaba de dar su consentimiento y guarda su connectedAccountId. Todas las llamadas posteriores reciben este UUID.

statusSignificado
CONNECTEDLas credenciales son válidas. Puedes iniciar la búsqueda de coincidencias.
MATCH_IN_PROGRESSHay un proceso de búsqueda de coincidencias en cola o en ejecución.
CONNECTIVITY_ISSUELa autorización ha caducado. connectivityIssue indica el motivo; vuelve a generar el enlace de conexión.

El filtro de consulta opcional status usa términos distintos (Connected, NotConnected, ConnectionIssue); si envías el valor status del propio registro como filtro, se devuelve un 400.

3. Inicia la búsqueda de coincidencias

La búsqueda de coincidencias obtiene todos los perfiles a los que la cuenta puede acceder y empareja cada uno con una de tus ubicaciones. Solo genera sugerencias; todavía no se vincula nada.

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"] } }'

La respuesta es data.connectedAccountsTriggerMatches con success y failedIds. success: true significa que el trabajo se puso en cola; cualquier cuenta que no se haya podido poner en cola aparece en failedIds.

4. Consulta periódicamente hasta que se alcance MATCH_COMPLETED

Consulta los detalles de la cuenta cada 15 segundos mediante un bucle con un límite de iteraciones. Este intervalo también mantiene el plan Launch dentro de su límite de 10 solicitudes por minuto.

Poll details
curl https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/details \-H "Authorization: API $LISTINGSAPI_KEY"

El registro se devuelve en data.connectedAccountDetails.details y tiene los mismos campos que un registro de la lista. requestMatchesStatus tiene el valor MATCH_IN_PROGRESS mientras se ejecuta el trabajo y MATCH_COMPLETED cuando las sugerencias están listas. Completed significa que la búsqueda de coincidencias ha terminado, no que se haya vinculado nada: connectedLocationsCount permanece en 0 hasta que lo confirmes.

5. Revisa y confirma las sugerencias

Cada sugerencia empareja una de tus ubicaciones (locationInfo, con locationId como su databaseId) con una ficha de Google (suggestedLocationInfo). Muestra ambos elementos a un operador o acepta la sugerencia automáticamente cuando coincidan el nombre y la ciudad.

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, "totalRecords": 2 },      "records": [        {          "accountType": "GMB",          "matchedDataDatabaseId": "0d5e306f-0da0-46e3-929f-fd3c67ccd8cc",          "locationId": "73415",          "locationInfo": { "name": "My Business", "city": "Lincoln", "stateIso": "NE" },          "suggestedLocationInfo": { "locationInfo": { "name": "My Business", "city": "Lincoln" } }        }      ]    }  }}

Una sugerencia no tiene id. Para confirmarla, construye un id de registro de coincidencia: la codificación en base64 de <MatchRecordType>:<matchedDataDatabaseId>, con el tipo elegido de accountType. Para Google (GMB), el tipo es GmbLocationMatchedData, por lo que el registro anterior se codifica como R21iTG9jYXRpb25NYXRjaGVkRGF0YTowZDVlMzA2Zi0wZGEwLTQ2ZTMtOTI5Zi1mZDNjNjdjY2Q4Y2M=. Facebook (FB) usa FbLocationMatchedData y Apple (APPLE) usa AppleLocationMatchedData.

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="] } }'

La respuesta es data.confirmConnectMatches con success y failedIds. failedIds contiene los valores matchedDataDatabaseId decodificados que no se pudieron confirmar, como un registro ya utilizado o una ubicación archivada después de la búsqueda de coincidencias. Un id construido con el tipo incorrecto no devuelve un 400: la llamada devuelve 200 con success: false y sin failedIds, así que comprueba success cada vez. Las sugerencias no enviadas permanecen intactas.

6. Importa fichas que aún no tienen una ubicación

La búsqueda de coincidencias solo vincula fichas con ubicaciones que ya tienes. Para importar las demás, enumera todas las fichas que la cuenta puede ver y luego crea una ubicación a partir de cada ficha que quieras.

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 }'
JSON
{  "data": {    "connectedAccountListings": {      "pageInfo": { "hasNextPage": false, "totalRecords": 60 },      "records": [        {          "id": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA==",          "locationName": "Trial",          "address": "123 William St, NY 10038, Manhattan, US",          "liveLink": null        }      ]    }  }}

Pasa locationInfo con un término de búsqueda para filtrar las fichas de una cuenta grande por nombre, dirección, teléfono, código postal o código de tienda. El valor de id de cada registro es el connectedAccountListingId que reciben las dos llamadas siguientes. Ninguno de los SDK ofrece aún una función para create-location-from-listing, por lo que los ejemplos de Python y Node llaman directamente a REST con la misma cabecera.

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 }  }}

La ubicación se crea a partir de los datos de Google (nombre, dirección, horarios, categorías, teléfono, atributos) y se vincula de inmediato a la ficha. La ficha de Google permanece en IN_PROGRESS hasta que se publique en ella tu primera actualización de la ubicación. locationId es el databaseId sin formato. Si se produce un error, success es false y errors contiene un código como SY81067 (no se encontró la ficha correspondiente al id). El campo es connectedAccountListingId; el esquema rechaza listingId.

Si la ficha pertenece a una ubicación que ya tienes, vincúlala en lugar de crear un duplicado.

Link a 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=="  }}'

Si la vinculación falla, devuelve success: false con un message, por ejemplo Listing record not found, o una nota que indica que la ficha ya está conectada a otra ubicación.

7. Conecta una sola ubicación como alternativa

Cuando ya sabes qué ubicación está conectando el propietario, omite la búsqueda de coincidencias y crea un enlace asociado a esa ubicación. Si la operación se completa correctamente, el propietario vuelve a tu successUrl y las credenciales se asocian únicamente a esa ubicación.

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"  }}'

La respuesta es data.createConnectUrl con success, url y errors. El enlace es de un solo uso, así que crea uno nuevo para cada intento. Una URL de redirección relativa o que no se pueda analizar da lugar a una respuesta success: true con un null url, así que comprueba url. Una clave que no tenga permiso para operar sobre esta ubicación recibe un 403 con SY90003.

8. Qué ocurre después

Una vez vinculada una ficha, la fila de Google Maps en las fichas prémium de la ubicación sale de REQUIRING_ACTION, pasa por IN_PROGRESS y queda en SYNCED con un listingUrl. Google se añade automáticamente como fuente de reseñas, por lo que las reseñas empiezan a aparecer en la lista de interacciones y las actualizaciones que haces en la ubicación se envían al perfil.

Si configuras una URL de webhook en el panel, no necesitas hacer consultas periódicas. Cada carga útil contiene location_id y data.connected_account_id.

EventoSe activa cuandoQué hacer
connection.location_connectedSe vincula una ficha a una ubicación; data.platform es google.Marca la ubicación como conectada en tu interfaz.
connection.reauth_requiredSe han invalidado las credenciales de la cuenta. No se sincroniza nada hasta que se vuelva a autorizar el acceso.Crea un enlace nuevo (paso 1) y pide al propietario que vuelva a iniciar sesión.
connection.listing_inaccessibleLas credenciales son válidas, pero se ha retirado el acceso a esa ficha concreta.Pide al propietario que restablezca el acceso en Google o vincula otra ficha.

Siguientes pasos