SDKsNode.js-SDK

SDKs

Node.js-SDK

Installiere @sofia-post/node und nutze die Sofia API aus Node.js: veröffentlichen, planen, Medien hochladen, Statistiken lesen – mit typisierten Fehlern.

Das offizielle Node.js-SDK verpackt die Sofia API v1 in einer einzigen Klasse, Sofia: eine Methode pro Route, typisierte Anfragen und Antworten und ein einziger Fehlertyp für jeden Fehlschlag. Es hat keine Abhängigkeiten und läuft ab Node.js 20.

Installation

Das SDK liegt auf npm als Paket @sofia-post/node. Es funktioniert mit import und require.

npm install @sofia-post/node

Schnellstart

Erstelle einen Client mit deinem Schlüssel, such den Betrieb, für den du veröffentlichen willst, und plane dann einen Beitrag auf 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);

Authentifizierung

Der Konstruktor nimmt einen persönlichen Schlüssel, den du unter Einstellungen › API, Tab Persönlicher Zugriff, erstellst, oder ein OAuth-Zugriffstoken, wenn deine Anwendung für andere Sofia-Nutzer handelt (OAuth2). Das SDK sendet ihn bei jeder Anfrage als Authorization: Bearer ….

Der Client spricht standardmäßig mit https://api.sofia-post.com. Das zweite Argument ändert die Basis-URL oder das fetch, mit dem er Anfragen sendet:

const sofia = new Sofia(apiKey, { baseUrl: 'http://localhost:3008' });

Methoden

MethodeWas sie tut
me()Für wen der Schlüssel handelt, seine Scopes und ob es ein Testschlüssel ist
platforms()Die Regeln jedes Netzwerks: Textlänge, Medien, Formate
establishments()Die Betriebe, die der Schlüssel erreicht
accounts(establishmentId)Die mit einem Betrieb verbundenen Social-Media-Konten
connectionLink(establishmentId, input)Eine von Sofia gehostete Seite, auf der die Person ein Netzwerk verbindet
insights(establishmentId, period?)Reichweite, Interaktion und Follower, Netzwerk für Netzwerk
post(input, options?)Jetzt veröffentlichen, mit scheduledAt planen oder einen Entwurf speichern
postList(filters?)Eine Seite mit Beiträgen, gefiltert nach Betrieb, Status oder Datum
getPost(id) · updatePost(id, input) · deletePost(id)Einen Beitrag lesen, ändern oder zurückziehen
upload(input) · uploadFromUrl(input)Eine Datei oder eine URL zur Mediathek des Betriebs hinzufügen
mediaList(filters) · getMedia(id) · deleteMedia(id)Die Mediathek lesen und aufräumen
createWebhook(input) · webhooks() · deleteWebhook(id) · testWebhook(id)Benachrichtigt werden, wenn ein Beitrag veröffentlicht wird oder fehlschlägt

Beiträge

Ein Beitrag hat pro Netzwerk ein Ziel, jeweils mit eigenem Text, eigenen Medien und eigenem Format. Prüfe ihn zuerst mit dryRun: Es wird nichts geschrieben, und eine Ablehnung listet jede verletzte Regel auf. Gib einen idempotencyKey mit, damit eine wiederholte Anfrage nie doppelt veröffentlicht. scheduledAt akzeptiert ein Date oder einen ISO-8601-String.

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() });

Medien

Lade die Datei einmal hoch und trage dann ihre id in die media eines Beitrags ein. upload nimmt einen Buffer, ein Uint8Array oder einen Blob und liest den Content-Type aus dem Dateinamen, sofern du keinen contentType angibst. Bei uploadFromUrl lädt Sofia die Datei selbst herunter.

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' });

Paginierung

postList und mediaList antworten Seite für Seite. Übergib das nextCursor einer Seite als cursor des nächsten Aufrufs; die letzte Seite hat keins.

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);

Fehler

Jede Methode wirft einen SofiaApiError, wenn die API den Aufruf ablehnt. Er enthält den HTTP-status, den stabilen code des Fehler-Umschlags, seine details (bei einem abgelehnten Beitrag jede verletzte Netzwerkregel), die requestId für den Support und bei einem 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);
}

Ist die API gar nicht erreichbar, hat der Fehler den Code network_error und den Status 0. Das SDK wiederholt nie von selbst: Warte bei einem 429 retryAfterSeconds ab und erhöhe bei einem 5xx die Abstände zwischen den Versuchen.

TypeScript

Das Paket bringt seine Typen mit: PublishPostInput, Post, Media, SocialAccount, EstablishmentInsights und die übrigen werden neben Sofia exportiert, damit dein Editor jedes Feld und jeden Enum-Wert vervollständigt.

Als Nächstes: Die API-Referenz beschreibt jede Route, die das SDK aufruft, und die CLI steuert dieselbe API vom Terminal aus.

War diese Seite hilfreich?