Social
Gérez les marques, liez les comptes sociaux et publiez ou planifiez des publications sur Facebook, Instagram, X, LinkedIn et Pinterest via client.social.
Toutes les méthodes Social se trouvent sous client.social, regroupées dans quatre espaces de noms, avec un appel supplémentaire au niveau supérieur :
Identifiants, plateformes et statuts
Les identifiants de marque, de publication et de connexion sont de simples chaînes UUID. Contrairement aux identifiants d'établissement, ils ne sont jamais encodés en Base64, et le SDK ne les transforme pas.
Les plateformes correspondent aux valeurs d'énumération en majuscules FACEBOOK, INSTAGRAM, TWITTER (qui désigne X), LINKEDIN et PINTEREST. Les statuts des publications sont DRAFT, PENDING, SCHEDULED, PUBLISHED, FAILED, ARCHIVED et REJECTED ; les statuts par canal sont SCHEDULED, SUCCESS, ERROR et ARCHIVED.
Chaque écriture renvoie un indicateur success
Les opérations d'écriture Social signalent les échecs de validation dans une réponse 200, sous la forme success: false, avec la raison dans error. Le SDK lève une exception en cas d'erreur de transport ou de contenu d'erreur qu'il reconnaît, mais prenez l'habitude de vérifier vous-même success :
result = client.social.brands.create(profile_name="Jenny Home", timezone=tz)if not result.success: raise RuntimeError(result.error.message)La publication est asynchrone
action="PUBLISH" accepte la publication et renvoie son id. Interrogez régulièrement social.posts.retrieve() et consultez connectedChannels[] pour obtenir les valeurs status, liveLink et error par canal ; une publication peut réussir sur une plateforme et échouer sur une autre lors du même appel.
social.brands.create
Créez une marque. Seuls profile_name et timezone sont obligatoires.
client.social.brands.create( *, profile_name: str, timezone: dict, business_intent: str | None = None, categories: list[str] | None = None, site_url: str | None = None, logo: str | None = None, country_iso: str | None = None, bio: str | None = None, brand_hashtags: list[str] | None = None, competitor_hashtags: list[str] | None = None, content_preferred_language: str | None = None,) -> APIObjectresult = client.social.brands.create( profile_name="Jenny Home", timezone={ "label": "(GMT-05:00) Eastern Time", "tzCode": "America/New_York", "name": "Eastern Standard Time", "utc": "-05:00", }, business_intent="A family-run home furnishings store selling handmade furniture.", categories=["Furniture Store"], site_url="https://jennyhome.example",)brand_id = result.socialProfile.id # a plain UUID stringLe nombre de marques est illimité dans les forfaits API ; cette opération n'échoue donc jamais en raison d'une limite. Ce sont les connexions qui sont comptabilisées — vérifiez social.limits() avant de générer un lien de connexion, et non avant de créer une marque.
social.brands.list
Listez les marques avec une pagination par décalage. statuses est obligatoire dans le filtre lorsque vous en envoyez un.
client.social.brands.list( *, statuses: list[str] | None = None, profile_name: str | None = None, page: int | None = None, size: int | None = None,) -> APIObjectresult = client.social.brands.list(page=1, size=25)for brand in result.profiles: print(brand.id, brand.profileName, brand.connectedChannelCount)print(result.pageInfo.total, result.pageInfo.hasNextPage)social.brands.retrieve
Récupérez une marque à partir de son UUID.
client.social.brands.retrieve(brand_id: str) -> APIObjectbrand = client.social.brands.retrieve("6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902")print(brand.profileName, brand.timezone.tzCode)social.brands.update
Mettez à jour une marque. Seul profile_id est obligatoire ; envoyez uniquement les champs que vous modifiez.
client.social.brands.update( profile_id: str, *, profile_name: str | None = None, timezone: dict | None = None, business_intent: str | None = None, categories: list[str] | None = None, site_url: str | None = None, logo: str | None = None, country_iso: str | None = None, bio: str | None = None, brand_hashtags: list[str] | None = None, competitor_hashtags: list[str] | None = None, content_preferred_language: str | None = None,) -> APIObjectcategories, brand_hashtags et competitor_hashtags remplacent la liste enregistrée lorsqu'ils sont envoyés ; transmettre [] la vide.
client.social.brands.update( "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", profile_name="Jenny Home & Co.",)social.brands.archive
Archivez une marque et ses connexions. La marque doit avoir été créée depuis au moins 90 jours.
client.social.brands.archive(social_profile_id: str) -> APIObjectresult = client.social.brands.archive("6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902")print(result.status) # ARCHIVED or TENURE_NOT_METPour une marque créée depuis moins de 90 jours, la réponse contient success: False et status: "TENURE_NOT_MET", et rien ne change. Une fois cette ancienneté atteinte, l'archivage est immédiat : la marque et toutes les connexions qui lui sont liées sont archivées lors du même appel et cessent immédiatement de publier, mais leurs emplacements de connexion restent occupés jusqu'à la fin du cycle de facturation, exactement comme lors d'une déconnexion manuelle.
social.connections.link
Générez une URL hébergée de courte durée qui guide un utilisateur final pour connecter une plateforme à une marque. Redirigez-le vers url.
client.social.connections.link( brand_id: str, *, channel: str, redirect_url: str, error_url: str | None = None, state: str | None = None,) -> APIObjectlink = client.social.connections.link( "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", channel="INSTAGRAM", redirect_url="https://app.example.com/social/connected", error_url="https://app.example.com/social/connect-failed", state="sess_9f2c1e64",)print(link.url, link.expiresIn)L'utilisateur revient à redirect_url avec status, brandId, platform, votre state et, en cas de réussite, connectedAccountId ajoutés à l'URL. La connexion est créée quelques instants plus tard ; interrogez donc régulièrement social.connections.list() pendant quelques secondes plutôt que de considérer le premier résultat vide comme un échec. Instagram nécessite un compte professionnel ou créateur lié à une Page Facebook.
social.connections.list
Listez les comptes de réseaux sociaux rattachés à une marque.
client.social.connections.list(brand_id: str) -> APIObjectresult = client.social.connections.list("6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902")for channel in result.socialConnected: print(channel.id, channel.platform, channel.displayName)print(result.channelCount)channel.id est l'UUID de connexion attendu par tous les autres appels ; referenceId est l'identifiant du compte propre à la plateforme et n'est jamais accepté en entrée.
social.connections.disconnect
Supprimez une connexion. Cette opération est irréversible : la rétablir nécessite un nouvel appel à social.connections.link().
client.social.connections.disconnect(social_profile_connected_channel_id: str) -> APIObjectclient.social.connections.disconnect("b81d5b3c-4a90-4f6a-9c11-71e0dd2fa4a7")Les publications planifiées ciblant le canal ne sont pas annulées ; elles échouent au moment de la publication avec SY95045. Annulez-les d'abord avec social.posts.cancel().
social.posts.create
Créez une publication pour une marque sur ses canaux connectés.
client.social.posts.create( *, social_profile_id: str, name: str, platforms: list[str], content: str, action: str, media_urls: list[str] | None = None, video_urls: list[str] | None = None, link: str | None = None, scheduled_at: str | None = None, schedule_date: str | None = None, schedule_time: str | None = None, connected_channel_ids: list[str] | None = None, client_reference: str | None = None,) -> APIObjectaction="SCHEDULE" nécessite exactement une forme de planification : scheduled_at, ou schedule_date + schedule_time. L'envoi des deux est rejeté avec SY95046.
result = client.social.posts.create( social_profile_id="6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", name="Autumn collection launch", platforms=["INSTAGRAM", "FACEBOOK"], content="Our autumn collection lands today. Solid oak, hand-finished.", media_urls=["https://cdn.example.com/social/autumn.jpg"], action="SCHEDULE", schedule_date="2026-10-02", schedule_time="09:30",)print(result.success, result.socialPostId)social.posts.retrieve
Récupérez une publication avec son état de publication par canal. Interrogez régulièrement cette méthode après une création.
client.social.posts.retrieve(post_id: str) -> APIObjectpost = client.social.posts.retrieve("c47a1e58-2b93-4f10-a6d7-58e0c9b12345")print(post.status)for channel in post.connectedChannels: print(channel.platform, channel.status, channel.liveLink, channel.error)social.posts.list
Listez les publications d'une marque avec une pagination par décalage et des filtres.
client.social.posts.list( brand_id: str, *, filters: dict | None = None, page: int | None = None, size: int | None = None, fetch_post_content: bool | None = None,) -> APIObjectfilters accepte name, platforms, status, start_date, end_date, social_connected_channel_id, approval_state, view_mode et filter_by_user.
result = client.social.posts.list( "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", filters={"status": ["SCHEDULED"], "startDate": "2026-10-01", "endDate": "2026-10-31"}, page=1, size=50,)for post in result.socialPosts: print(post.socialPostId, post.name, post.status)print(result.pageInfo.total)social.posts.cancel
Annulez une publication planifiée ou à l'état de brouillon pour qu'elle ne soit jamais publiée.
client.social.posts.cancel(social_post_id: str) -> APIObjectclient.social.posts.cancel("c47a1e58-2b93-4f10-a6d7-58e0c9b12345")Les publications déjà publiées ne peuvent pas être annulées et ne sont retirées d'aucune plateforme ; l'appel renvoie success: False pour celles-ci.
social.posts.insights
Interactions et commentaires pour une publication publiée sur un canal donné. Les deux champs sont renvoyés sous forme de chaînes JSON contenant les données propres à la plateforme.
client.social.posts.insights( post_id: str, *, social_connected_channel_id: str,) -> APIObjectimport json result = client.social.posts.insights( "c47a1e58-2b93-4f10-a6d7-58e0c9b12345", social_connected_channel_id="b81d5b3c-4a90-4f6a-9c11-71e0dd2fa4a7",)insights = json.loads(result.insights)comments = json.loads(result.comments)print(insights.get("impressions"), len(comments))Les clés qu'elles contiennent sont propres à chaque plateforme et varient d'une plateforme à l'autre ; prévoyez les cas inattendus lors de leur lecture.
social.bulk.create
Validez et mettez en file d'attente jusqu'à 500 publications dans une seule requête. Les lignes peuvent cibler différentes marques.
client.social.bulk.create( posts: list[dict], *, name: str | None = None,) -> APIObjectChaque ligne accepte les mêmes champs que social.posts.create, dans camelCase. Si une seule ligne est invalide, rien n'est créé : success vaut False, SY95050 est renvoyé dans error, et job.results[] identifie chaque ligne incorrecte par son index indexé à partir de 0 et son clientReference.
result = client.social.bulk.create([ { "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", "name": "Autumn week 1", "platforms": ["INSTAGRAM", "FACEBOOK"], "content": "Week one of the autumn collection.", "mediaUrls": ["https://cdn.example.com/social/autumn-w1.jpg"], "action": "SCHEDULE", "scheduleDate": "2026-10-02", "scheduleTime": "09:30", "clientReference": "campaign-4471-slot-01", },])if not result.success: for row in result.job.results: print(row.index, row.clientReference, row.errors)else: job_id = result.job.idsocial.bulk.retrieve
Interrogez régulièrement une tâche de traitement en masse jusqu'à ce qu'elle atteigne un statut final.
client.social.bulk.retrieve(bulk_job_id: str) -> APIObjectjob = client.social.bulk.retrieve("9b3f18d0-7a26-4c51-8e94-1f0d5c6b7a82")print(job.status, job.processedCount, "/", job.totalCount)for row in job.results: print(row.clientReference, row.status, row.socialPostId)status vaut QUEUED, PROCESSING, COMPLETED, COMPLETED_WITH_ERRORS ou FAILED. Lorsqu'une ligne atteint CREATED, cela signifie que la publication existe, et non qu'elle a été publiée : transmettez socialPostId à social.posts.retrieve() pour obtenir le résultat par canal.
social.limits
Limite de connexions et utilisation actuelle, en un seul appel.
client.social.limits() -> APIObjectlimits = client.social.limits()print(limits.maxConnections, limits.usage.connections) # pool vs usedprint(limits.brands) # None — brands are unlimitedprint(limits.usage.brands) # brands that exist, uncappedLes connexions constituent un quota partagé à l'échelle du compte — 20 avec Social Launch, 125 avec Social Growth, plus 5 pour chaque pack de connexions à 25 $/mois — et non un quota par marque. Vérifiez-le avant de générer un lien de connexion afin de pouvoir proposer une mise à niveau plutôt que d'afficher SY95042. limits.brands vaut None dans tous les forfaits API.
Voir aussi
- Forfaits et modules complémentaires : niveaux, tarifs des modules complémentaires, pool de connexions et règle des 90 jours d’ancienneté
- Référence REST Social : les points de terminaison bruts que ces méthodes encapsulent
- Publications : le produit à l’échelle de l’établissement, avec un abonnement distinct
- Gestion des erreurs : exceptions typées et indicateur
success