SDK
SDK Node.js
Installa @sofia-post/node e chiama l’API Sofia da Node.js: pubblica, programma, carica media e leggi le statistiche, con risposte ed errori tipizzati.
L’SDK Node.js ufficiale racchiude l’API Sofia v1 in un’unica classe, Sofia: un metodo per route, richieste e risposte tipizzate e un solo tipo di errore per ogni fallimento. Non ha dipendenze e funziona con Node.js 20 o successivo.
Installazione
L’SDK è pubblicato su npm come pacchetto @sofia-post/node. Funziona sia con import sia con require.
npm install @sofia-post/nodePer iniziare
Crea un client con la tua chiave, trova l’attività per cui pubblicare, poi programma un post su Instagram:
import { Sofia } from '@sofia-post/node';
const sofia = new Sofia(process.env.SOFIA_API_KEY);
const [establishment] = await sofia.establishments();
const post = await sofia.post({
establishmentId: establishment.id,
targets: [{ platform: 'instagram', text: 'Tarte tatin du jour 🍎' }],
scheduledAt: new Date('2026-12-01T09:00:00Z'),
});
console.log(post.id, post.status);Autenticazione
Il costruttore accetta una chiave personale, creata in Impostazioni › API, scheda Accesso personale, oppure un token di accesso OAuth se la tua applicazione agisce per altri utenti di Sofia (OAuth2). L’SDK lo invia come Authorization: Bearer … a ogni richiesta.
Il client parla con https://api.sofia-post.com per impostazione predefinita. Il secondo argomento cambia l’URL di base o il fetch con cui invia le richieste:
const sofia = new Sofia(apiKey, { baseUrl: 'http://localhost:3008' });Metodi
| Metodo | Cosa fa |
|---|---|
me() | Per chi agisce la chiave, i suoi scope e se è una chiave di test |
platforms() | Le regole di ogni rete: lunghezza del testo, media, formati |
establishments() | Le attività che la chiave raggiunge |
accounts(establishmentId) | Gli account social collegati a un’attività |
connectionLink(establishmentId, input) | Una pagina ospitata da Sofia dove la persona collega una rete |
insights(establishmentId, period?) | Copertura, engagement e follower, rete per rete |
post(input, options?) | Pubblicare subito, programmare con scheduledAt o salvare una bozza |
postList(filters?) | Una pagina di post, filtrati per attività, stato o date |
getPost(id) · updatePost(id, input) · deletePost(id) | Leggere, modificare o ritirare un post |
upload(input) · uploadFromUrl(input) | Aggiungere un file o un URL alla libreria media dell’attività |
mediaList(filters) · getMedia(id) · deleteMedia(id) | Leggere e riordinare la libreria media |
createWebhook(input) · webhooks() · deleteWebhook(id) · testWebhook(id) | Essere avvisati quando un post esce o fallisce |
Post
Un post ha una destinazione per rete, ciascuna con il proprio testo, i propri media e il proprio formato. Verificalo prima con dryRun: non viene scritto nulla e un rifiuto elenca ogni regola violata. Passa una idempotencyKey perché una richiesta ripetuta non pubblichi mai due volte. scheduledAt accetta una Date o una stringa ISO 8601.
import type { PublishPostInput } from '@sofia-post/node';
const input: PublishPostInput = {
establishmentId,
targets: [
{ platform: 'instagram', text: 'Menu du jour', media: [{ id: media.id }] },
{ platform: 'facebook', text: 'Menu du jour : tarte tatin et café' },
],
};
await sofia.post(input, { dryRun: true });
await sofia.post(input, { idempotencyKey: crypto.randomUUID() });Media
Carica il file una volta, poi metti il suo id nei media di un post. upload accetta un Buffer, un Uint8Array o un Blob e ricava il tipo di contenuto dal nome del file, a meno che tu non indichi contentType. Con uploadFromUrl è Sofia a scaricare il file.
import { readFile } from 'node:fs/promises';
const media = await sofia.upload({
establishmentId,
file: await readFile('tarte-tatin.jpg'),
fileName: 'tarte-tatin.jpg',
});
const imported = await sofia.uploadFromUrl({ establishmentId, url: 'https://example.com/menu.png' });Paginazione
postList e mediaList rispondono una pagina alla volta. Passa il nextCursor di una pagina come cursor della chiamata successiva; l’ultima pagina non ne ha.
let cursor: string | undefined;
do {
const page = await sofia.postList({ establishmentId, status: 'published', limit: 100, cursor });
page.data.forEach((post) => console.log(post.id));
cursor = page.nextCursor;
} while (cursor);Errori
Ogni metodo lancia un SofiaApiError quando l’API rifiuta la chiamata. Contiene lo status HTTP, il code stabile della busta di errore, i suoi details (per un post rifiutato, ogni regola di rete violata), il requestId da comunicare al supporto e, su un 429, retryAfterSeconds.
import { SofiaApiError } from '@sofia-post/node';
try {
await sofia.post(input);
} catch (error) {
if (!(error instanceof SofiaApiError)) throw error;
if (error.code === 'post_refused') console.log(error.details);
if (error.status === 429) await wait(error.retryAfterSeconds);
}Quando l’API non è raggiungibile affatto, l’errore ha il codice network_error e lo status 0. L’SDK non riprova mai da solo: attendi retryAfterSeconds su un 429 e distanzia i tentativi su un 5xx.
TypeScript
Il pacchetto include i suoi tipi: PublishPostInput, Post, Media, SocialAccount, EstablishmentInsights e gli altri sono esportati accanto a Sofia, così il tuo editor completa ogni campo e ogni valore di enumerazione.
Poi: il riferimento API descrive ogni route che l’SDK chiama, e la CLI pilota la stessa API da un terminale.