Pubblicazioni
Pubblicare una pubblicazione
Le app live pubblicano subito, programmano o salvano una bozza; quelle di test simulano soltanto. Con ?dry_run=true controlla tutto e non scrive nulla.
Un post appartiene a un’attività ed esce verso una o più reti, le sue destinazioni. Ogni destinazione ha il suo testo, i suoi media, il suo formato e il suo stato.
Tipo di post: subito, programmato o bozza
Due campi del corpo decidono quando, e se, il post esce:
| Caso | Corpo | Comportamento |
|---|---|---|
| Subito | senza scheduledAt | Il post esce subito. |
| Programmato | scheduledAt: una data-ora ISO 8601 futura | Uscirà a scheduledAt. |
| Bozza | "status": "draft", senza scheduledAt | Viene salvato e non esce. |
Il corpo di un post
| Campo | Significato |
|---|---|
establishmentId | L’attività che pubblica (GET /v1/establishments) |
targets[] | Una voce per rete: platform, text, e in opzione media, format e accountId |
targets[].media[] | Un media della libreria tramite il suo id, oppure un url https pubblico con il suo type (image o video) |
targets[].accountId | L’account da usare quando l’attività ne ha più di uno su quella rete |
scheduledAt | Una data-ora ISO 8601 futura; se assente, il post esce subito |
status | draft per salvare una bozza che non esce (allora senza scheduledAt) |
Media di una destinazione
Ogni voce di targets[].media designa un media della libreria tramite il suo id, oppure un url https pubblico con il suo type (image o video). Instagram e TikTok richiedono una foto o un video. Per aggiungere un media alla libreria, vedi Importare un media.
Duplicare un post
Non esiste un endpoint dedicato per duplicare un post: leggilo con `GET /v1/posts/{id}`, poi rinvia il suo contenuto in una nuova richiesta POST /v1/posts.
Prima di rinviarlo, togli i campi che Sofia compila da sola. Come minimo:
idecreatedAtdel post;statusdel post letto (riassume lo stato di invio): imposta quello che vuoi, oppure omettilo;- in ogni destinazione:
state,publishedAt,permalinkeerror.
Conserva establishmentId, e per ogni destinazione platform e accountId. La lettura non restituisce il testo delle destinazioni né i loro media: forniscili di nuovo. Imposta infine un nuovo scheduledAt (oppure omettilo per pubblicare subito, o invia "status": "draft").
Il tuo primo post
1. Verificare le reti collegate
Un post esce tramite gli account collegati all’attività. Elencali; se ne manca uno, crea un link di collegamento. Vedi Account collegati.
2. Aggiungere un media
Instagram e TikTok richiedono una foto o un video. Importane uno da un URL https pubblico; Sofia lo scarica nella libreria media e restituisce il suo id. Vedi Importare un media.
3. Verificare con una simulazione
Aggiungi ?dry_run=true: Sofia giudica ogni rete secondo le sue regole reali e l’account collegato, e non scrive nulla.
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. Pubblicare
Invia lo stesso corpo senza dry_run, con una Idempotency-Key perché un nuovo tentativo non pubblichi mai due volte. Senza scheduledAt, il post esce subito; con un scheduledAt futuro, viene programmato.
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. Seguirlo
Il post risponde publishing, poi ogni rete passa a published con il suo permalink, o a failed con il suo motivo. Leggilo con `GET /v1/posts/{id}`, oppure registra un webhook per essere avvisato.
Simulazione (dry run)
POST /v1/posts?dry_run=true esegue i controlli di un vero post: le regole di ogni rete, l’account collegato, i media, la data e il tuo piano. Non salva nulla e non invia nulla.
Pronto
Quando ogni rete accetterebbe il post, la risposta è 200 con status: "ready" e, per ogni destinazione, l’account che pubblicherebbe.
Rifiutato
Altrimenti la risposta è 422 post_refused, con un dettaglio per motivo. Ogni dettaglio nomina la sua rete, il suo code, e dice cosa correggere.
{
"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"
}
}Ogni motivo è elencato negli errori.
Per la modalità test delle applicazioni, vedi Modalità test e simulazione. Una Idempotency-Key protegge anche POST /v1/posts: vedi Idempotenza.
Autorizzazioni
AuthorizationstringheaderobbligatorioLa tua chiave personale o il token di accesso OAuth, inviato come
Bearer <token>.
Parametri di query
dry_runstringtrue: esegue ogni controllo dell'invio (regole delle reti, account, media, creazione, abbonamento live) e non scrive nulla. Restituisce 200readyo 422post_refused.Valori ammessi:
truefalse
Header
Idempotency-KeystringRipetuta con lo stesso body, la richiesta restituisce la stessa risposta senza creare una seconda pubblicazione. Una simulazione non consuma la chiave.
Body
establishmentIdstringobbligatorioAttività, nel Workspace dell'autorizzazione del token (
GET /v1/establishments)targetsobject[]obbligatorioUna rete per destinazione
Mostra gli attributi figli
platformstringobbligatorioRete di destinazione
Valori ammessi:
instagramfacebookxlinkedintiktoktextstringobbligatorioDidascalia pubblicata su questa rete
mediaobject[]Media allegati
Mostra gli attributi figli
idstringIdentificatore di un media della mediateca dell'attività (altrimenti
urletype)urlstringIndirizzo pubblico del media (https in live); senza identificatore
typestringTipo del media dato per indirizzo
Valori ammessi:
imagevideo
formatstringFormato (
post,reel,story,carousel...); per default, quello che la rete offrirebbeaccountIdstringLive: l'account collegato che pubblica, quando l'attività ne ha più di uno su questa rete (
GET /v1/establishments/:id/accounts)
scheduledAtstring<date-time>Data di programmazione (ISO 8601), nel futuro; assente: pubblica subito. Non ammessa con
statusdraftstatusstringdraft: una bozza (solo live), creata senza data, non viene inviato nulla;PATCH /v1/posts/:idla programmaValori ammessi:
draft
Risposta
Simulazione: tutti i controlli sono passati.
statusstringobbligatorioSempre
readyValori ammessi:
readydryRunbooleanobbligatorioSempre
trueValori ammessi:
truetargetsobject[]obbligatorioLe destinazioni controllate
Mostra gli attributi figli
platformstringobbligatorioRete della destinazione
statestringobbligatorioSempre
readyValori ammessi:
readyaccountIdstringLive: l'account che pubblicherebbe
handlestringLive: il suo handle visualizzato