Publicaciones
Endpoints de publicaciones con cURL/Python/Node: anuncios, eventos, ofertas, programación, campañas por ubicación y masivas, consulta de estado y borrado.
Una publicación es una actualización breve publicada en el perfil de Google Business Profile o en la página de Facebook de una ubicación: un anuncio, un evento con fechas o una oferta con un cupón. Una campaña puede dirigirse a muchas ubicaciones y a ambos sitios a la vez. La publicación es asíncrona, por lo que cada llamada de creación devuelve una respuesta inmediatamente y debes consultar periódicamente el resultado. Los tres endpoints GET funcionan con una clave Read (lectura); para crear y eliminar se necesita una clave Write (escritura).
Resumen de los endpoints
Valores que usarás en todos los casos
Todos los endpoints de creación comparten las cuatro enumeraciones siguientes.
Publicar un anuncio
POST /posts
Un anuncio acepta un mensaje y, opcionalmente, un botón y una imagen por sitio. Proporciona una entrada postMessage para cada sitio incluido en postSites. La respuesta devuelve la nueva campaña con status establecido en INPROGRESS, porque la publicación se ejecuta en segundo plano.
Parámetros
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "postName": "Grand Opening Announcement", "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="], "postType": "ANNOUNCEMENT", "postSites": ["GOOGLE"], "postMessage": [ { "site": "GOOGLE", "message": "We are now open! Visit us this week for our grand opening." } ], "postCta": [ { "site": "GOOGLE", "type": "LEARN_MORE", "url": "https://jennyhome.example/opening" } ], "postMediaUrl": [ { "site": "GOOGLE", "url": "https://cdn.example.com/opening.jpg", "type": "IMAGE" } ] }}'{ "data": { "createSocialPost": { "success": true, "errors": [], "socialPost": { "id": "U29jaWFsUG9zdDo0NDEyMg==", "name": "Grand Opening Announcement", "status": "INPROGRESS", "type": "ANNOUNCEMENT", "sites": ["GOOGLE"], "publishDetails": [ { "site": "GOOGLE", "status": "PUBLISHING", "createdDate": "2026-06-28", "submissionError": null } ], "postLinks": [], "locationIds": [1800289] } } }}Guarda socialPost.id. Es el ID de la publicación en base64 que necesitan todos los demás endpoints de esta página. Las funciones auxiliares de ambos SDK aceptan una única cadena message y la expanden en una entrada por sitio, por lo que solo tienes que construir manualmente el array postMessage en cURL.
Publicar un evento
POST /posts
Un evento se muestra como una tarjeta con fechas. La programación del propio evento está en postContextInfo. El objeto independiente postScheduledDates controla cuándo aparece y caduca la publicación en sí, lo que suele corresponder al período previo al evento. Google rechaza los eventos sin título, y ambos SDK generan un error de validación antes del envío si falta title.
Parámetros
Todo lo indicado en la tabla del anuncio también se aplica.
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "postName": "Summer Sale Kickoff Event", "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="], "postType": "EVENT", "postSites": ["GOOGLE"], "postContextInfo": { "title": "Summer Sale Kickoff", "startDay": "2026-07-15", "startTime": "10:00am", "endDay": "2026-07-15", "endTime": "06:00pm" }, "postMessage": [ { "site": "GOOGLE", "message": "Join us for the Summer Sale kickoff, refreshments and up to 40 percent off in store." } ] }}'{ "data": { "createSocialPost": { "success": true, "socialPost": { "id": "U29jaWFsUG9zdDo0NDEyMw==", "status": "INPROGRESS", "type": "EVENT", "scheduledStartDate": "2026-07-15", "scheduledEndDate": "2026-07-15", "contextInfo": { "title": "Summer Sale Kickoff", "startDay": "2026-07-15", "startTime": "10:00am", "endDay": "2026-07-15", "endTime": "06:00pm" } } } }}El valor contextInfo devuelto es el intervalo del evento. scheduledStartDate y scheduledEndDate describen la programación de la propia publicación, que en este caso coincide con las fechas del evento porque no se envió postScheduledDates.
Publicar una oferta
POST /posts
Una oferta es una tarjeta promocional que contiene un código de cupón, un descuento, un enlace de canje y las condiciones. Todo eso va en postContextInfo, y startDay junto con endDay delimitan la validez de la oferta en lugar de la de la publicación.
Parámetros
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "postName": "Festive 25 Percent Off", "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="], "postType": "OFFER", "postSites": ["GOOGLE"], "postContextInfo": { "title": "25% off storewide", "couponCode": "FESTIVE25", "discount": "25%", "redeemUrl": "https://jennyhome.example/festive", "termsConditions": "Valid in-store only through July 6.", "startDay": "2026-06-22", "endDay": "2026-07-06" }, "postMessage": [ { "site": "GOOGLE", "message": "Celebrate with us, 25 percent off everything in store this week." } ], "postCta": [ { "site": "GOOGLE", "type": "GET_OFFER", "url": "https://jennyhome.example/festive" } ] }}'{ "data": { "createSocialPost": { "success": true, "socialPost": { "id": "U29jaWFsUG9zdDo0NDEyNA==", "status": "INPROGRESS", "type": "OFFER", "contextInfo": { "title": "25% off storewide", "couponCode": "FESTIVE25", "discount": "25%", "startDay": "2026-06-22", "endDay": "2026-07-06" } } } }}Google acepta ORDER y Facebook acepta GET_OFFER para los botones de las ofertas. Si una promoción termina antes de tiempo, elimina la campaña en lugar de editarla.
Consultar una publicación y su estado
GET /posts/{postId}
Devuelve el resultado publicado de una campaña aceptada. Responde bajo data.socialPostView con el contenido de la campaña, una entrada publishDetails por sitio, contadores de interacción y los enlaces activos una vez que la publicación se completa correctamente.
Parámetros
curl https://listingsapi.com/api/v4/posts/U29jaWFsUG9zdDo0NDEyMg== \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "socialPostView": { "socialPostId": "U29jaWFsUG9zdDo0NDEyMg==", "socialPostInfo": { "status": "SUCCESS", "type": "ANNOUNCEMENT", "views": 128, "clicks": 14, "publishDetails": [ { "site": "GOOGLE", "status": "PUBLISHED", "publishedDate": "2026-06-28", "submissionError": null } ], "postLinks": [ { "site": "GOOGLE", "link": "https://www.google.com/maps/place/?post=44122" } ] }, "publishedLocationsCount": 1, "socialPostAnalyticsBySite": [ { "site": "GOOGLE", "views": 128, "clicks": 14, "reactions": 3, "shares": 0, "comments": 1 } ] } }}Hay dos campos de estado relevantes, y cada uno responde a una pregunta distinta.
Una campaña puede mostrar SUCCESS mientras uno de sus sitios tiene ERROR, así que comprueba siempre publishDetails en lugar de consultar solo el estado de nivel superior.
Listar las publicaciones de una ubicación
GET /locations/{locationId}/posts
Un historial paginado por desplazamiento de todas las campañas que incluyen una ubicación, bajo data.postsByLocation. Úsalo para revisar lo que ya está activo antes de programar algo nuevo.
Parámetros
curl "https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/posts?page=1&perPage=10" \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "postsByLocation": { "records": [ { "id": "U29jaWFsUG9zdDo0NDEyMg==", "name": "Summer Hours Update", "status": "SUCCESS", "type": "ANNOUNCEMENT", "createdAt": "2026-06-28", "views": 128, "clicks": 14, "sites": ["GOOGLE"] } ], "pageInfo": { "totalPages": 1, "hasNextPage": false, "totalRecords": 1 } } }}Esta ruta no tiene ningún filtro en el servidor. Solo acepta page y perPage e ignora todo lo demás, así que consulta type y status en cada registro y filtra en tu propio código. Para ordenar y filtrar en el servidor, usa el endpoint de listado masivo que se describe a continuación.
Eliminar una publicación
DELETE /posts/{postId}
Es permanente y retira la publicación de todos los sitios en los que se publicó. No se puede deshacer ni existe un endpoint de edición, por lo que corregir una publicación activa implica eliminarla y publicar otra que la sustituya.
Parámetros
curl -X DELETE https://listingsapi.com/api/v4/posts/U29jaWFsUG9zdDo0NDEyMg== \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "clientMutationId": "delete-44122-req-1" }'{ "data": { "deleteSocialPost": { "success": true, "socialPostId": "U29jaWFsUG9zdDo0NDEyMg==" } }}Eliminar una publicación desconocida o ya eliminada devuelve una respuesta de error con data establecido en null en lugar de success: false.
Publicar una campaña en muchas ubicaciones
POST /bulk-posts
El mismo contrato que POST /posts, diseñado para conjuntos de ubicaciones: incluye todas las ubicaciones en locationIds y una sola campaña las abarcará todas. La respuesta se devuelve bajo la clave createSocialPost, igual que en POST /posts.
Parámetros
curl -X POST https://listingsapi.com/api/v4/bulk-posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "postName": "July Reopening Announcement", "locationIds": ["TG9jYXRpb246MTgwMDI4OQ==", "TG9jYXRpb246MTgwMDI5MA=="], "postType": "ANNOUNCEMENT", "postSites": ["GOOGLE", "FACEBOOK"], "postMessage": [ { "site": "GOOGLE", "message": "We are back. Visit us this week for our summer menu." }, { "site": "FACEBOOK", "message": "We are back. Swing by for the new summer menu." } ], "postScheduledDates": { "startDatetime": "2026-07-10T09:00:00Z", "endDatetime": "2026-07-24T23:59:00Z" } }}'{ "data": { "createSocialPost": { "success": true, "errors": null, "socialPost": { "id": "U29jaWFsUG9zdDo5OTIwMQ==", "name": "July Reopening Announcement", "status": "SCHEDULED", "type": "ANNOUNCEMENT", "scheduledStartDate": "2026-07-10", "scheduledEndDate": "2026-07-24", "sites": ["GOOGLE", "FACEBOOK"], "locationIds": [1800289, 1800290] } } }}Las funciones auxiliares de ambos SDK establecen Google y Facebook como valor predeterminado de sites, expanden por ti un mapa de mensajes por sitio y codifican los identificadores numéricos de las ubicaciones, por lo que una publicación masiva suele ser la llamada más corta en cualquiera de los dos SDK.
Consultar una campaña masiva
GET /bulk-posts/{postId}
El equivalente masivo de GET /posts/{postId}. Devuelve la misma estructura, con publishedLocationsCount mayor que uno y un desglose de analíticas por tienda en socialPostAnalyticsByLocationId.
Parámetros
curl https://listingsapi.com/api/v4/bulk-posts/U29jaWFsUG9zdDo1MTA4OA== \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "socialPostView": { "socialPostId": "U29jaWFsUG9zdDo1MTA4OA==", "socialPostInfo": { "name": "Festive Offer - All Stores", "status": "SUCCESS", "type": "OFFER", "views": 4210, "clicks": 318, "sites": ["GOOGLE", "FACEBOOK"] }, "socialPostAnalyticsByLocationId": [ { "locationId": 1800289, "siteStats": [ { "site": "GOOGLE", "status": "PUBLISHED", "views": 1040, "clicks": 80 }, { "site": "FACEBOOK", "status": "PUBLISHED", "views": 360, "clicks": 26 } ] } ] } }}socialPostAnalyticsBySite suma los totales de la campaña en todas las tiendas, mientras que socialPostAnalyticsByLocationId desglosa las mismas cifras por tienda. Revisa los valores de status de cada tienda para encontrar cualquier ubicación en la que haya fallado un sitio.
Listar campañas masivas de una ubicación
GET /locations/{locationId}/bulk-posts
Usa paginación por desplazamiento bajo data.rollupSocialPosts. A diferencia de la lista por ubicación, esta ruta sí admite filtros y ordenación, lo que la convierte en el endpoint adecuado para un panel de campañas.
Parámetros
Los campos por los que puedes ordenar son name, type, status, created_at, schedule_start_date, schedule_end_date, client_name, clicks, views y shares.
curl -G https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/bulk-posts \-H "Authorization: API $LISTINGSAPI_KEY" \--data-urlencode 'page=1' \--data-urlencode 'perPage=10' \--data-urlencode 'sortFields={"field":"created_at","order":"Descending"}'{ "data": { "rollupSocialPosts": { "records": [ { "id": "U29jaWFsUG9zdDo1MTA4OA==", "name": "Festive Offer - All Stores", "status": "SUCCESS", "type": "OFFER", "createdAt": "2026-06-20", "views": 4210, "clicks": 318 } ], "pageInfo": { "totalPages": 1, "hasNextPage": false, "totalRecords": 1 } } }}Ambos SDK codifican en JSON los objetos filters y sortFields por ti, así que pásalos como diccionarios u objetos nativos.
Errores que verás
La lista completa está en Códigos de error.
Próximos pasos
- Publicar contenido: la versión práctica de esta página, con una campaña programada explicada de principio a fin.
- Comprobar el estado de las fichas y los enlaces activos: confirma que una ubicación esté publicada en Google antes de enviarle una publicación.
- Conectar Google e importar ubicaciones: una ubicación necesita una cuenta conectada para que cualquier sitio acepte una publicación.
- Reaccionar a eventos con webhooks: los eventos
local_postsustituyen las consultas periódicas de los resultados de publicación. - Referencia de publicaciones para consultar la lista completa de campos de cada endpoint anterior.