/api/v4/bulk-postsCréer une publication en masse
Crée une publication sur les réseaux sociaux et la publie sur plusieurs établissements en une seule requête.
Paramètres
Corps
Un champ imbriqué marqué comme obligatoire ne s’applique que si vous envoyez son parent. Si le parent est facultatif et que vous l’omettez, ses champs enfants obligatoires ne s’appliquent pas.
| Nom | Type | Obligatoire | Description |
|---|---|---|---|
| input | object | obligatoire | Wrapper object. Every field below is a property of `input`, the entire body must be nested under it. |
| input.postName | string | obligatoire | Internal name for the campaign (not shown publicly). |
| input.locationIds | array of strings | obligatoire | Base64-encoded location Relay IDs to publish to. |
| input.postType | string | obligatoire | One of `EVENT`, `OFFER`, `ANNOUNCEMENT`, `COVID19`, `PRODUCT`. |
| input.postSites | array of strings | obligatoire | Target publishers: `GOOGLE` and/or `FACEBOOK`. |
| input.postMessage | array of objects | facultatif | Per-site post body. Each entry: `site` and `message`. |
| input.postMessage[].site | string | obligatoire | Publisher for this message: `GOOGLE` or `FACEBOOK`. |
| input.postMessage[].message | string | obligatoire | Post body text for that site. |
| input.postMediaUrl | array of objects | facultatif | Per-site media. Each entry: `site`, `url`, and `type` (`IMAGE` or `VIDEO`). |
| input.postMediaUrl[].site | string | obligatoire | Publisher for this media asset. |
| input.postMediaUrl[].url | string | obligatoire | Publicly accessible media URL. |
| input.postMediaUrl[].type | string | facultatif | `IMAGE` or `VIDEO`. |
| input.postCta | array of objects | facultatif | Per-site call-to-action button. Each entry: `site`, `type`, `url`. |
| input.postScheduledDates | object | facultatif | Scheduling window: `startDatetime`, `endDatetime`, and optional `removalSites`. When provided, the post is created with status `SCHEDULED`. |
| input.postScheduledDates.startDatetime | string | obligatoire | ISO-8601 datetime the post goes live. |
| input.postScheduledDates.endDatetime | string | obligatoire | ISO-8601 datetime the post is removed. |
| input.postContextInfo | object | facultatif | Type-specific details (offer coupon/redeem/terms, or event title/times). Required by `OFFER`, `EVENT`, and `PRODUCT` posts. |
| input.products | array of objects | facultatif | Product entries for `PRODUCT` posts (name, price, photo, cta). |
| input.componentIdentifier | string | facultatif | Optional client component reference for tracking. |
| input.componentType | string | facultatif | Optional client component type for tracking. |
Exemple de requête
Corps prêt à coller. Remplacez les identifiants et valeurs d’exemple par les vôtres.
{ "input": { "postName": "July Reopening Announcement", "locationIds": [ "TG9jYXRpb246MTgwMDI4OQ==", "TG9jYXRpb246MTgwMDI5MA==" ], "postType": "ANNOUNCEMENT", "postSites": ["GOOGLE", "FACEBOOK"], "postMessage": [ { "site": "GOOGLE", "message": "We're back! Visit us this week for our summer menu." }, { "site": "FACEBOOK", "message": "We're back! Swing by for the new summer menu." } ], "postMediaUrl": [ { "site": "GOOGLE", "url": "https://cdn.example.com/summer.jpg", "type": "IMAGE" } ], "postScheduledDates": { "startDatetime": "2026-07-10T09:00:00Z", "endDatetime": "2026-07-24T23:59:00Z" } }}Réponses
200Bulk post accepted. `success` is true and the created campaign is returned. Note the response is keyed under `createSocialPost`: the bulk endpoint returns the same response shape as `POST /posts`.
{ "data": { "createSocialPost": { "clientMutationId": null, "success": true, "errors": null, "socialPost": { "id": "U29jaWFsUG9zdDo5OTIwMQ==", "name": "July Reopening Announcement", "status": "SCHEDULED", "type": "ANNOUNCEMENT", "createdAt": "2026-07-08", "scheduledStartDate": "2026-07-10", "scheduledEndDate": "2026-07-24", "sites": ["GOOGLE", "FACEBOOK"], "locationIds": [1800289, 1800290] } } }}400Bad request, the body was not wrapped in `input` (error message: `Variable "$input" of required type ... was not provided`).
401Unauthenticated, missing or invalid API key.
Crée une seule campagne de publication et la diffuse à chaque établissement de locationIds, en publiant sur les postSites sélectionnés. Contrairement à la création par établissement, un seul appel cible l'ensemble de vos établissements, ce qui permet de diffuser efficacement une annonce, une offre ou un événement à l'échelle de l'entreprise.
Structure de la requête. Le corps entier doit être encapsulé dans un objet input ; chaque champ (postName, locationIds, postType, …) est une propriété de input. Un corps à plat, non encapsulé, est rejeté avec un statut HTTP 400 (Variable "$input" of required type ... was not provided). Le contrat est identique à celui de POST /posts, et une réponse de succès utilise la clé createSocialPost plutôt qu'une clé propre à la publication en masse.
Cas d'utilisation : annonce à l'échelle de l'entreprise (illustré ci-dessus). Définissez postType: "ANNOUNCEMENT", indiquez les identifiants des établissements et fournissez un postMessage par établissement. Ajoutez postScheduledDates pour diffuser la publication sur une période définie (la publication est alors créée avec le statut SCHEDULED) ; omettez-le pour publier immédiatement.
Cas d'utilisation : offre à durée limitée dans tous les magasins. Remplacez la valeur de postType par OFFER et fournissez le coupon dans postContextInfo (toujours encapsulé dans input) :
{ "input": { "postName": "Summer 20% Off", "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="], "postType": "OFFER", "postSites": ["GOOGLE"], "postMessage": [{ "site": "GOOGLE", "message": "20% off through July!" }], "postContextInfo": { "title": "Summer Sale", "couponCode": "SUMMER20", "redeemUrl": "https://example.com/offer", "termsConditions": "Valid through July 31", "startDay": "2026-07-10", "startTime": "09:00", "endDay": "2026-07-31", "endTime": "23:59" } }}Points de vigilance.
- Le corps doit être encapsulé dans
input; si vous envoyez les champs au premier niveau, le point de terminaison renvoie un statut HTTP 400. postType,postSites,postNameetlocationIdssont obligatoires ; les typesEVENT,OFFERetPRODUCTnécessitent également les champspostContextInfo(ouproducts) correspondants.postSitesaccepte uniquementGOOGLEetFACEBOOK; le canal correspondant doit être connecté pour chaque établissement ciblé, sinon cet établissement est ignoré.- En cas d'échec partiel ou total de la validation, la réponse contient un statut HTTP 200 avec
success: falseet un tableauerrorsrenseigné ; vérifiezsuccess, puis suivez la diffusion en temps réel par établissement à l'aide du point de terminaison de récupération d'une publication en masse.
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're back! Visit us this week for our summer menu." }, { "site": "FACEBOOK", "message": "We're back! Swing by for the new summer menu." } ], "postMediaUrl": [ { "site": "GOOGLE", "url": "https://cdn.example.com/summer.jpg", "type": "IMAGE" } ], "postScheduledDates": { "startDatetime": "2026-07-10T09:00:00Z", "endDatetime": "2026-07-24T23:59:00Z" } } }'