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.
1. Crea el enlace de conexión y redirige al propietario
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.
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" }}'{ "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.
curl "https://listingsapi.com/api/v4/connected-accounts?publisher=GoogleAccount&page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"{ "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.
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.
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.
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.
curl "https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/connection-suggestions?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"{ "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.
# 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.
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 }'{ "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.
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==" }}'{ "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.
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.
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.
Siguientes pasos
- Crea un Google Business Profile: para una ubicación que no tiene una ficha de Google con la que buscar coincidencias.
- Conecta páginas de Facebook: el mismo flujo para la otra plataforma de publicación que usa OAuth.
- Consulta el estado de las fichas y los enlaces activos y Obtén reseñas: observa cómo van llegando los resultados.
- Referencias de los SDK: Cuentas conectadas en Python y Cuentas conectadas en Node.
- Referencia: Conecta una cuenta de Google, Inicia la búsqueda de coincidencias de ubicaciones, Confirma las coincidencias de conexión, Obtén las fichas de una cuenta conectada, Crea una ubicación a partir de una ficha y el índice de Cuentas conectadas.