Publications
Publier une publication
Une application live publie aussitôt, programme ou enregistre un brouillon ; en test, elle simule. Avec ?dry_run=true, tout est vérifié et rien n’est écrit.
Une publication appartient à un établissement et part vers un ou plusieurs réseaux, ses cibles. Chaque cible a son propre texte, ses médias, son format et son état.
Type de publication : maintenant, programmée ou brouillon
Deux champs du corps décident quand, et si, la publication part :
| Cas | Corps | Comportement |
|---|---|---|
| Maintenant | sans scheduledAt | La publication part tout de suite. |
| Programmée | scheduledAt : une date-heure ISO 8601 future | Elle partira à scheduledAt. |
| Brouillon | "status": "draft", sans scheduledAt | Elle est enregistrée et ne part pas. |
Le corps d’une publication
| Champ | Signification |
|---|---|
establishmentId | L’établissement qui publie (GET /v1/establishments) |
targets[] | Une entrée par réseau : platform, text, et en option media, format et accountId |
targets[].media[] | Un média de la médiathèque par son id, ou une url https publique avec son type (image ou video) |
targets[].accountId | Le compte à utiliser quand l’établissement en a plusieurs sur ce réseau |
scheduledAt | Une date-heure ISO 8601 future ; absente, la publication part tout de suite |
status | draft pour enregistrer un brouillon qui ne part pas (sans scheduledAt alors) |
Médias d’une cible
Chaque entrée de targets[].media désigne un média de la médiathèque par son id, ou une url https publique avec son type (image ou video). Instagram et TikTok exigent une photo ou une vidéo. Pour ajouter un média à la médiathèque, voir Importer un média.
Dupliquer une publication
Il n’existe pas d’endpoint dédié pour dupliquer une publication : lisez-la avec `GET /v1/posts/{id}`, puis renvoyez son contenu dans une nouvelle requête POST /v1/posts.
Avant de la renvoyer, retirez les champs que Sofia renseigne elle-même. Au minimum :
idetcreatedAtde la publication ;statusde la publication lue (il résume l’état d’envoi) : fixez celui que vous voulez, ou omettez-le ;- dans chaque cible :
state,publishedAt,permalinketerror.
Gardez establishmentId, et pour chaque cible platform et accountId. La lecture ne renvoie pas le texte des cibles ni leurs médias : fournissez-les de nouveau. Fixez enfin un nouveau scheduledAt (ou omettez-le pour publier tout de suite, ou envoyez "status": "draft").
Votre première publication
1. Vérifier les réseaux connectés
Une publication part par les comptes connectés à l’établissement. Listez-les ; s’il en manque un, créez un lien de connexion. Voir Comptes connectés.
2. Ajouter un média
Instagram et TikTok exigent une photo ou une vidéo. Importez-en une depuis une URL https publique ; Sofia la télécharge dans la médiathèque et renvoie son id. Voir Importer un média.
3. Vérifier avec une simulation
Ajoutez ?dry_run=true : Sofia juge chaque réseau selon ses règles réelles et le compte connecté, et n’écrit rien.
curl -X POST 'https://api.sofia-post.com/api/v1/posts?dry_run=true' \
-H "Authorization: Bearer $SOFIA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"establishmentId": "'$ESTABLISHMENT_ID'",
"targets": [
{ "platform": "instagram", "text": "Tarte tatin du jour", "media": [{ "id": "'$MEDIA_ID'" }] },
{ "platform": "facebook", "text": "Tarte tatin du jour", "media": [{ "id": "'$MEDIA_ID'" }] }
]
}'{
"status": "ready",
"dryRun": true,
"targets": [
{ "platform": "instagram", "accountId": "fecd0904-…", "handle": "sof_ia_officiel", "state": "ready" },
{ "platform": "facebook", "accountId": "a423b3a4-…", "handle": "Sofia post", "state": "ready" }
]
}4. Publier
Envoyez le même corps sans dry_run, avec une Idempotency-Key pour qu’un nouvel essai ne publie jamais deux fois. Sans scheduledAt, la publication part tout de suite ; avec un scheduledAt futur, elle est programmée.
curl -X POST https://api.sofia-post.com/api/v1/posts \
-H "Authorization: Bearer $SOFIA_API_KEY" \
-H 'Content-Type: application/json' \
-H "Idempotency-Key: $(uuidgen)" \
-d @post.json5. La suivre
La publication répond publishing, puis chaque réseau passe à published avec son lien permanent, ou à failed avec sa raison. Lisez-la avec `GET /v1/posts/{id}`, ou enregistrez un webhook pour être prévenu.
Simulation (dry run)
POST /v1/posts?dry_run=true exécute les contrôles d’une vraie publication : les règles de chaque réseau, le compte connecté, les médias, la date et votre forfait. Il n’enregistre rien et n’envoie rien.
Prête
Quand chaque réseau accepterait la publication, la réponse est 200 avec status: "ready" et, pour chaque cible, le compte qui publierait.
Refusée
Sinon, la réponse est 422 post_refused, avec un détail par raison. Chaque détail nomme son réseau, son code, et dit quoi corriger.
{
"error": {
"code": "post_refused",
"message": "The post would not be published: x: the text is too long (300 characters, at most 280)",
"details": [
{
"platform": "x",
"code": "caption_too_long",
"max": 280,
"actual": 300,
"message": "x: the text is too long (300 characters, at most 280)"
}
],
"docUrl": "https://www.sofia-post.com/developers/errors#post_refused"
}
}Chaque raison est listée dans les erreurs.
Pour le mode test des applications, voir Mode test et simulation. Une Idempotency-Key protège aussi POST /v1/posts : voir Idempotence.
Autorisations
AuthorizationstringheaderrequisVotre clé personnelle ou jeton d’accès OAuth, envoyé sous la forme
Bearer <token>.
Paramètres de requête
dry_runstringtrue: exécute chaque contrôle que l’envoi ferait (règles des réseaux, comptes, médias, création, abonnement en ligne) et n’écrit rien. Renvoie 200readyou 422post_refused.Valeurs autorisées :
truefalse
En-têtes
Idempotency-KeystringRejouée avec le même corps, la requête renvoie la même réponse sans créer de seconde publication. Une simulation ne consomme pas la clé.
Corps
establishmentIdstringrequisÉtablissement, dans le Workspace de l’autorisation du jeton (
GET /v1/establishments)targetsobject[]requisUn réseau par cible
Afficher les attributs enfants
platformstringrequisRéseau visé
Valeurs autorisées :
instagramfacebookxlinkedintiktoktextstringrequisLégende publiée sur ce réseau
mediaobject[]Médias joints
Afficher les attributs enfants
idstringIdentifiant d’un média de la médiathèque de l’établissement (sinon
urlettype)urlstringAdresse publique du média (https en live) ; sans identifiant
typestringType du média donné par adresse
Valeurs autorisées :
imagevideo
formatstringFormat (
post,reel,story,carousel...) ; par défaut, celui que le réseau serviraitaccountIdstringEn live : le compte connecté qui publie, quand l’établissement en a plusieurs sur ce réseau (
GET /v1/establishments/:id/accounts)
scheduledAtstring<date-time>Date de programmation (ISO 8601), dans le futur ; absente : publication immédiate. Interdite avec
statusdraftstatusstringdraft: un brouillon (en live seulement), créé sans date, rien n’est envoyé ;PATCH /v1/posts/:idle programmeValeurs autorisées :
draft
Réponse
Simulation : tous les contrôles sont passés.
statusstringrequisToujours
readyValeurs autorisées :
readydryRunbooleanrequisToujours
trueValeurs autorisées :
truetargetsobject[]requisLes cibles vérifiées
Afficher les attributs enfants
platformstringrequisRéseau de la cible
statestringrequisToujours
readyValeurs autorisées :
readyaccountIdstringEn live : le compte qui publierait
handlestringEn live : son identifiant affiché