SDKsSDK de Node.js

SDKs

SDK de Node.js

Instala @sofia-post/node y llama a la API de Sofia desde Node.js: publica, programa, sube archivos y lee estadísticas, con respuestas y errores tipados.

El SDK oficial de Node.js envuelve la API v1 de Sofia en una sola clase, Sofia: un método por ruta, solicitudes y respuestas tipadas, y un único tipo de error para cualquier fallo. No tiene dependencias y funciona con Node.js 20 o posterior.

Instalación

El SDK se publica en npm como el paquete @sofia-post/node. Funciona tanto con import como con require.

npm install @sofia-post/node

Inicio rápido

Crea un cliente con tu clave, localiza el establecimiento para el que vas a publicar y programa una publicación en 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);

Autenticación

El constructor recibe una clave personal, que se crea en Ajustes › API, pestaña Acceso personal, o un token de acceso OAuth si tu aplicación actúa por otros usuarios de Sofia (OAuth2). El SDK la envía como Authorization: Bearer … en cada solicitud.

El cliente habla con https://api.sofia-post.com por defecto. El segundo argumento cambia la URL base o el fetch con el que envía las solicitudes:

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

Métodos

MétodoQué hace
me()Para quién actúa la clave, sus scopes y si es una clave de prueba
platforms()Las reglas de cada red: longitud del texto, archivos, formatos
establishments()Los establecimientos a los que llega la clave
accounts(establishmentId)Las cuentas sociales conectadas a un establecimiento
connectionLink(establishmentId, input)Una página alojada por Sofia donde la persona conecta una red
insights(establishmentId, period?)Alcance, interacción y seguidores, red por red
post(input, options?)Publicar ahora, programar con scheduledAt o guardar un borrador
postList(filters?)Una página de publicaciones, filtradas por establecimiento, estado o fechas
getPost(id) · updatePost(id, input) · deletePost(id)Leer, modificar o retirar una publicación
upload(input) · uploadFromUrl(input)Añadir un archivo o una URL a la biblioteca de archivos del establecimiento
mediaList(filters) · getMedia(id) · deleteMedia(id)Leer y limpiar la biblioteca de archivos
createWebhook(input) · webhooks() · deleteWebhook(id) · testWebhook(id)Recibir un aviso cuando una publicación sale o falla

Publicaciones

Una publicación tiene un destino por red, cada uno con su propio texto, archivos y formato. Compruébala primero con dryRun: no se escribe nada, y un rechazo enumera cada regla que incumple. Pasa una idempotencyKey para que una solicitud repetida nunca publique dos veces. scheduledAt acepta una Date o una cadena 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() });

Archivos

Sube el archivo una vez y pon su id en los media de una publicación. upload acepta un Buffer, un Uint8Array o un Blob, y lee el tipo de contenido del nombre del archivo salvo que indiques contentType. Con uploadFromUrl, Sofia descarga el archivo ella misma.

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

Paginación

postList y mediaList responden una página cada vez. Pasa el nextCursor de una página como cursor de la siguiente llamada; la última página no lo tiene.

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

Errores

Cada método lanza un SofiaApiError cuando la API rechaza la llamada. Incluye el status HTTP, el code estable del sobre de error, sus details (en una publicación rechazada, cada regla de red que incumple), el requestId que debes dar al soporte y, en 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);
}

Cuando la API no es accesible en absoluto, el error tiene el código network_error y el estado 0. El SDK nunca reintenta por su cuenta: espera retryAfterSeconds en un 429 y espacia los reintentos en un 5xx.

TypeScript

El paquete incluye sus tipos: PublishPostInput, Post, Media, SocialAccount, EstablishmentInsights y los demás se exportan junto a Sofia, para que tu editor autocomplete cada campo y cada valor de enumeración.

A continuación: la referencia de la API describe cada ruta que llama el SDK, y la CLI maneja la misma API desde un terminal.

¿Te ha resultado útil esta página?