Publications
Posts : exemples cURL/Python/Node ; annonces, événements, offres, planification, campagnes par établissement ou en masse, suivi du statut, suppression.
Une publication est une courte mise à jour publiée sur le profil Google Business Profile ou la page Facebook d'un établissement : une annonce, un événement daté ou une offre avec un coupon. Une campagne peut cibler plusieurs établissements et les deux sites à la fois. La publication est asynchrone : chaque appel de création renvoie donc immédiatement une réponse, et vous interrogez ensuite le statut pour obtenir le résultat. Les trois endpoints GET fonctionnent avec une clé Read (lecture) ; la création et la suppression nécessitent une clé Write (écriture).
Aperçu des endpoints
Valeurs utilisées partout
Les quatre énumérations ci-dessous sont communes à tous les endpoints de création.
Publier une annonce
POST /posts
Une annonce comprend un message et, éventuellement, un bouton et une image par site. Fournissez une entrée postMessage pour chaque site figurant dans postSites. La réponse renvoie la nouvelle campagne avec status défini sur INPROGRESS, car la publication s'effectue en arrière-plan.
Paramètres
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] } } }}Conservez socialPost.id. Il s'agit de l'identifiant de publication en base64 requis par tous les autres endpoints présentés ici. Les deux fonctions utilitaires des SDK acceptent une seule chaîne message et la déclinent en une entrée par site ; vous ne construisez donc le tableau postMessage manuellement que dans cURL.
Publier un événement
POST /posts
Un événement s'affiche sous forme de carte datée. Le calendrier propre à l'événement se trouve dans postContextInfo. L'objet distinct postScheduledDates contrôle le moment où la publication elle-même apparaît et expire, ce qui correspond généralement à la période précédant l'événement. Google rejette les événements sans titre, et les deux SDK lèvent une erreur de validation avant l'envoi si title est absent.
Paramètres
Tous les éléments du tableau des annonces s'appliquent également.
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" } } } }}La valeur contextInfo renvoyée correspond à la période de l'événement. scheduledStartDate et scheduledEndDate décrivent le calendrier propre à la publication, qui correspond ici aux dates de l'événement, car aucun postScheduledDates n'a été envoyé.
Publier une offre
POST /posts
Une offre est une carte promotionnelle contenant un code de réduction, une remise, un lien pour en bénéficier et des conditions. Tous ces éléments figurent dans postContextInfo, et startDay avec endDay délimitent la période de validité de l'offre plutôt que celle de la publication.
Paramètres
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 utilise ORDER et Facebook utilise GET_OFFER pour les boutons des offres. Si une promotion se termine plus tôt que prévu, supprimez la campagne plutôt que de la modifier.
Consulter une publication et son statut
GET /posts/{postId}
Renvoie le résultat de publication d'une campagne acceptée. La réponse contient, sous data.socialPostView, le contenu de la campagne, une entrée publishDetails par site, des compteurs d'engagement et les liens vers les publications en ligne une fois la publication réussie.
Paramètres
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 } ] } }}Deux champs de statut sont importants et répondent à des questions différentes.
Une campagne peut afficher SUCCESS alors que l'un de ses sites présente le statut ERROR ; vérifiez donc toujours publishDetails plutôt que de vous fier uniquement au statut de premier niveau.
Lister les publications d'un établissement
GET /locations/{locationId}/posts
Un historique paginé par décalage de toutes les campagnes qui incluent un établissement donné, sous data.postsByLocation. Utilisez-le pour vérifier ce qui est déjà en ligne avant de planifier une nouvelle publication.
Paramètres
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 } } }}Cette route ne propose aucun filtre côté serveur. Elle accepte uniquement page et perPage et ignore tout autre paramètre ; consultez donc type et status dans chaque enregistrement et appliquez le filtrage dans votre propre code. Pour trier et filtrer côté serveur, utilisez plutôt le point de terminaison de liste en masse ci-dessous.
Supprimer une publication
DELETE /posts/{postId}
La suppression est définitive et retire la publication de tous les sites sur lesquels elle a été publiée. Il n'existe ni annulation ni point de terminaison de modification ; pour corriger une publication en ligne, vous devez donc la supprimer et publier une nouvelle version.
Paramètres
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==" } }}La suppression d'une publication inconnue ou déjà supprimée renvoie une réponse d'erreur avec data défini sur null plutôt que sur success: false.
Publier une campagne pour plusieurs établissements
POST /bulk-posts
Le contrat est identique à celui de POST /posts, mais conçu pour les réseaux d'établissements : indiquez chaque établissement dans locationIds et une seule campagne les couvre tous. La réponse figure sous la clé createSocialPost, comme pour POST /posts.
Paramètres
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] } } }}Les fonctions utilitaires des deux SDK définissent par défaut sites sur Google et Facebook, développent pour vous une table de correspondance des messages par site et encodent les identifiants numériques des établissements ; la publication en masse est donc généralement l'appel le plus court dans chacun des SDK.
Lire une campagne de publication en masse
GET /bulk-posts/{postId}
L'équivalent de GET /posts/{postId} pour les publications en masse. Il renvoie la même structure, avec publishedLocationsCount supérieur à 1 et une ventilation des données analytiques par établissement dans socialPostAnalyticsByLocationId.
Paramètres
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 présente les totaux de la campagne pour l'ensemble des établissements, tandis que socialPostAnalyticsByLocationId ventile ces mêmes chiffres par établissement. Parcourez les valeurs de status par établissement pour repérer tout établissement pour lequel un site a rencontré un échec.
Lister les campagnes de publication en masse d'un établissement
GET /locations/{locationId}/bulk-posts
La liste est paginée par décalage sous data.rollupSocialPosts. Contrairement à la liste par établissement, cette route accepte les filtres et le tri, ce qui en fait l'endpoint adapté à un tableau de bord de campagnes.
Paramètres
Les champs utilisables pour le tri sont name, type, status, created_at, schedule_start_date, schedule_end_date, client_name, clicks, views et 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 } } }}Les deux SDK encodent les objets filters et sortFields en JSON pour vous ; transmettez-les donc sous forme de dictionnaires ou d'objets natifs.
Erreurs que vous rencontrerez
Liste complète dans Codes d'erreur.
Étapes suivantes
- Publier du contenu : la version pratique de cette page, qui détaille de bout en bout une campagne programmée.
- Vérifier le statut des fiches et les liens en ligne : confirmez qu'un établissement est en ligne sur Google avant d'y publier du contenu.
- Connecter Google et importer des établissements : un établissement doit disposer d'un compte connecté pour qu'un site accepte une publication.
- Réagir aux événements avec des webhooks : les événements
local_postremplacent les interrogations répétées pour obtenir les résultats de publication. - Référence des publications pour la liste complète des champs de chaque endpoint ci-dessus.