POST/api/v4/social/bulk-posts

Créer des publications en masse

Valide et met en file jusqu’à 500 publications sur les réseaux sociaux par requête et renvoie une tâche à interroger pour les résultats par ligne.

Nécessite une clé API. Consultez Authentification pour le format de l’en-tête et la rotation des clés.

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.

NomTypeObligatoireDescription
inputobjectobligatoireWrapper object. The entire request body must be nested under `input`.
input.postsarray of objectsobligatoireThe rows to create, 1 to 500 of them. Each row is the same object POST /social/posts takes as its `input`; the per-row fields are listed below.
input.namestringfacultatifOptional label for the job itself, to identify it in your own logs. Not shown to any audience.
input.posts[].socialProfileIdstringobligatoireUUID of the brand publishing this row. Rows may target different brands in one request.
input.posts[].namestringobligatoireInternal name for the post.
input.posts[].platformsarray of stringsobligatoirePlatforms for this row: `FACEBOOK`, `INSTAGRAM`, `TWITTER` (X), `LINKEDIN`, `PINTEREST`. Each must already have a connection on that row's brand.
input.posts[].contentstringobligatoireThe post body.
input.posts[].actionstringobligatoire`DRAFT`, `SCHEDULE` (requires a schedule) or `PUBLISH`.
input.posts[].mediaUrlsarray of stringsfacultatifPublic https image URLs. Required when the row targets Instagram or Pinterest.
input.posts[].videoUrlsarray of stringsfacultatifPublic https video URLs.
input.posts[].linkstringfacultatifLink to attach where the platform supports one.
input.posts[].scheduledAtstringfacultatifISO-8601 publish instant with an offset. Alternative to `scheduleDate` + `scheduleTime`, never both.
input.posts[].scheduleDatestringfacultatif`YYYY-MM-DD`, interpreted in that row's brand timezone. Send with `scheduleTime`.
input.posts[].scheduleTimestringfacultatif`HH:MM`, interpreted in that row's brand timezone. Send with `scheduleDate`.
input.posts[].connectedChannelIdsarray of stringsfacultatifRestrict this row to specific connections by ID.
input.posts[].clientReferencestringfacultatifYour own identifier for this row, echoed back on the matching job result. The most reliable way to reconcile a batch against your own records.

Exemple de requête

Corps prêt à coller. Remplacez les identifiants et valeurs d’exemple par les vôtres.

Request body
{  "input": {    "name": "Autumn campaign load",    "posts": [      {        "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902",        "name": "Autumn week 1",        "platforms": ["INSTAGRAM", "FACEBOOK"],        "content": "Week one of the autumn collection: the Fairfield oak sideboard, finished by hand in the workshop.",        "mediaUrls": ["https://cdn.example.com/social/autumn-w1.jpg"],        "action": "SCHEDULE",        "scheduleDate": "2026-10-02",        "scheduleTime": "09:30",        "clientReference": "campaign-4471-slot-01"      },      {        "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902",        "name": "Autumn week 2",        "platforms": ["INSTAGRAM", "FACEBOOK", "LINKEDIN"],        "content": "Week two: the Halcyon armchair. Sixty hours of work, one chair.",        "mediaUrls": ["https://cdn.example.com/social/autumn-w2.jpg"],        "action": "SCHEDULE",        "scheduleDate": "2026-10-09",        "scheduleTime": "09:30",        "clientReference": "campaign-4471-slot-02"      },      {        "socialProfileId": "a90f7c22-5db1-4e83-9f40-2b7c6a1e5d33",        "name": "Eastside autumn teaser",        "platforms": ["INSTAGRAM"],        "content": "Something solid is arriving next week. Stay tuned.",        "mediaUrls": ["https://cdn.example.com/social/eastside-teaser.jpg"],        "action": "SCHEDULE",        "scheduledAt": "2026-10-01T08:00:00-04:00",        "clientReference": "campaign-4471-slot-03"      }    ]  }}

Réponses

200The whole batch validated. A job was queued, poll GET /social/bulk-posts/{bulkJobId} for per-row results.
Response
{  "data": {    "createBulkSocialMediaPosts": {      "success": true,      "error": [],      "job": {        "id": "9b3f18d0-7a26-4c51-8e94-1f0d5c6b7a82",        "status": "QUEUED",        "totalCount": 3,        "processedCount": 0,        "successCount": 0,        "failureCount": 0,        "createdAt": "2026-09-28T14:04:52Z",        "updatedAt": "2026-09-28T14:04:52Z",        "results": []      }    }  }}
200At least one row failed validation, so **nothing was created**. `success` is `false`, no job is returned, and each rejected row is reported with its 0-based `index`.
Response
{  "data": {    "createBulkSocialMediaPosts": {      "success": false,      "error": [        {          "message": "SY95050: Bulk validation failed, no posts were created",          "code": "SY95050",          "contextInfo": null        }      ],      "job": {        "id": null,        "status": "FAILED",        "totalCount": 3,        "processedCount": 0,        "successCount": 0,        "failureCount": 2,        "createdAt": "2026-09-28T14:04:52Z",        "updatedAt": "2026-09-28T14:04:52Z",        "results": [          {            "index": 1,            "clientReference": "campaign-4471-slot-02",            "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902",            "platforms": ["INSTAGRAM", "FACEBOOK", "LINKEDIN"],            "status": "INVALID",            "socialPostId": null,            "postStatus": null,            "errors": [              {                "message": "SY95045: No connected channel for LINKEDIN on this brand",                "code": "SY95045",                "contextInfo": [{ "key": "platform", "value": "LINKEDIN" }]              }            ]          },          {            "index": 2,            "clientReference": "campaign-4471-slot-03",            "socialProfileId": "a90f7c22-5db1-4e83-9f40-2b7c6a1e5d33",            "platforms": ["INSTAGRAM"],            "status": "INVALID",            "socialPostId": null,            "postStatus": null,            "errors": [              {                "message": "SY95046: scheduledAt must carry a UTC offset",                "code": "SY95046",                "contextInfo": null              }            ]          }        ]      }    }  }}
401Unauthenticated, missing or invalid API key.

Crée plusieurs publications sur les réseaux sociaux en une seule requête. Les lignes sont transmises dans le corps de la requête — aucun téléversement de fichier ni CSV, simplement un tableau contenant les mêmes objets que POST /social/posts accepte un par un. Jusqu'à 500 lignes par requête.

Cas d'utilisation : charger un trimestre de contenu en un seul appel. Votre outil de planification contient l'intégralité du calendrier de contenu du client. Créez une ligne par créneau, associez à chacune votre propre clientReference, puis envoyez-les ensemble. Le lot réussit dans son ensemble ou vous indique précisément les lignes à corriger. Enregistrez le job.id renvoyé et interrogez périodiquement GET /social/bulk-posts/{bulkJobId} jusqu'à ce que status atteigne un état final, puis rapprochez chaque résultat de vos données à l'aide de son clientReference.

L'ensemble du lot est validé au préalable

La validation porte sur chaque ligne avant toute création, et le lot est atomique à ce stade :

  • Si une seule ligne est invalide, rien n'est créé. success vaut false, SY95050 est renvoyé dans error, et chaque ligne incorrecte apparaît dans job.results[] avec son index indexé à partir de 0, son clientReference et la raison dans errors[]. Corrigez ces lignes et renvoyez l'ensemble du lot.
  • Si toutes les lignes sont valides, une tâche est mise en file d'attente, success vaut true et vous obtenez un job.id. Certaines lignes peuvent encore échouer plus tard, lorsque la plateforme les rejette au moment de la publication ; cet échec apparaît dans la tâche, pas ici.

Rapprochez les résultats de vos données à l'aide de clientReference lorsque c'est possible, et de index sinon — les lignes elles-mêmes ne sont pas renvoyées, ces deux champs sont donc le seul lien avec vos propres données.

Remarques.

  • Le corps de la requête doit être encapsulé dans un objet input, avec les lignes dans input.posts.
  • Vérifiez success, pas le statut HTTP. Un rejet de l'ensemble du lot est un HTTP 200 avec success: false et SY95050 dans error.
  • Maximum 500 lignes par requête. Un tableau plus grand est rejeté d'emblée avec SY95048 et rien n'est créé ; divisez-le et envoyez plusieurs lots.
  • La marque de chaque ligne est socialProfileId. brandId est exclusivement un paramètre de chemin d'URL, et cette route ne comporte aucun paramètre de chemin.
  • Les lignes peuvent cibler différentes marques. Les platforms de chaque ligne sont vérifiés par rapport à la marque de cette même ligne ; une plateforme connectée à une marque mais pas à une autre ne fait donc échouer que les lignes qui en ont besoin.
  • Chaque ligne suit les mêmes règles de planification qu'une publication individuelle : scheduledAt ou scheduleDate + scheduleTime, jamais les deux, et scheduleDate / scheduleTime sont interprétés dans le fuseau horaire de la marque de cette ligne. Vous pouvez utiliser les deux formes sur des lignes différentes d'un même lot.
  • Les limites de débit s'appliquent à la requête, pas aux lignes : un lot de 500 lignes consomme une requête sur votre quota. Consultez Limites de débit.

Opération d'écriture : non exécutée sur le compte réel. La requête et la réponse présentées sont construites à partir du schéma de l'API ; l'exécution de cette requête publie sur de véritables comptes de réseaux sociaux.

Request
curl -X POST 'https://listingsapi.com/api/v4/social/bulk-posts' \  -H "Authorization: API $LISTINGSAPI_KEY" \  -H 'Content-Type: application/json' \  -d '{    "input": {      "name": "Autumn campaign load",      "posts": [        {          "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902",          "name": "Autumn week 1",          "platforms": [            "INSTAGRAM",            "FACEBOOK"          ],          "content": "Week one of the autumn collection: the Fairfield oak sideboard, finished by hand in the workshop.",          "mediaUrls": [            "https://cdn.example.com/social/autumn-w1.jpg"          ],          "action": "SCHEDULE",          "scheduleDate": "2026-10-02",          "scheduleTime": "09:30",          "clientReference": "campaign-4471-slot-01"        },        {          "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902",          "name": "Autumn week 2",          "platforms": [            "INSTAGRAM",            "FACEBOOK",            "LINKEDIN"          ],          "content": "Week two: the Halcyon armchair. Sixty hours of work, one chair.",          "mediaUrls": [            "https://cdn.example.com/social/autumn-w2.jpg"          ],          "action": "SCHEDULE",          "scheduleDate": "2026-10-09",          "scheduleTime": "09:30",          "clientReference": "campaign-4471-slot-02"        },        {          "socialProfileId": "a90f7c22-5db1-4e83-9f40-2b7c6a1e5d33",          "name": "Eastside autumn teaser",          "platforms": [            "INSTAGRAM"          ],          "content": "Something solid is arriving next week. Stay tuned.",          "mediaUrls": [            "https://cdn.example.com/social/eastside-teaser.jpg"          ],          "action": "SCHEDULE",          "scheduledAt": "2026-10-01T08:00:00-04:00",          "clientReference": "campaign-4471-slot-03"        }      ]    }  }'