> ## Documentation Index
> Fetch the complete documentation index at: https://docs.so-me.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Publicaciones y multimedia

> Publica al instante, programa publicaciones y sube archivos multimedia para clientes embebidos

Las publicaciones pertenecen a un usuario final y deben dirigirse a una de las conexiones
sociales de ese usuario final. La plataforma de `connectionId` debe coincidir con `socialMedia`.

## Crear una publicación de texto

Omite `scheduledAt` para poner la publicación en cola de inmediato:

```ts theme={null}
const post = await soMe.posts.create(
  endUser.id,
  {
    connectionId: connection.id,
    socialMedia: "THREADS",
    postType: "TEXT",
    text: "Published through our app",
  },
  { idempotencyKey: "customer_123:post_456" },
);
```

Para programarla, pasa una marca de tiempo ISO 8601:

```ts theme={null}
const post = await soMe.posts.create(
  endUser.id,
  {
    connectionId: connection.id,
    socialMedia: "THREADS",
    postType: "TEXT",
    text: "See you tomorrow",
    scheduledAt: "2026-08-20T10:00:00Z",
  },
  { idempotencyKey: "customer_123:post_457" },
);
```

> [!WARNING]
>
> Usa una clave de idempotencia estable y única para cada publicación lógica. Si tu solicitud
> agota el tiempo de espera, reintenta con la misma clave. Las claves deben tener entre 1 y 255 caracteres y
> están limitadas al espacio de trabajo del usuario final.

## Listar y recuperar publicaciones

```ts theme={null}
const page = await soMe.posts.list(endUser.id, {
  page: 1,
  limit: 20,
});

const post = await soMe.posts.get(endUser.id, "post_uuid");
```

`limit` está limitado a un valor entre 1 y 100. La respuesta de la lista contiene `data`, `page`,
`limit` y `total`.

## Subir archivos multimedia

Las subidas de archivos multimedia siguen un flujo de tres pasos:

1. Solicita a Social media studio una URL de subida prefirmada.
2. Sube los bytes del archivo sin procesar directamente a esa URL con HTTP `PUT`. Envía una
   cabecera `Content-Type` igual al `mimetype` que declaraste: la URL se firma con él,
   así que un `PUT` sin él, o con otro valor, falla con
   `403 SignatureDoesNotMatch`.
3. Adjunta la información del archivo devuelta al crear la publicación.

```ts theme={null}
import { readFile, stat } from "node:fs/promises";

const filename = "launch.jpg";
const mimetype = "image/jpeg";
const size = (await stat(filename)).size;

const [media] = await soMe.posts.presignMedia(endUser.id, {
  postType: "IMAGE",
  socialMedia: "THREADS",
  files: [{ filename, mimetype, size }],
});

const upload = await fetch(media.uploadUrl, {
  method: "PUT",
  headers: { "Content-Type": mimetype },
  body: await readFile(filename),
});

if (!upload.ok) {
  throw new Error(`Media upload failed: ${upload.status}`);
}

const post = await soMe.posts.create(
  endUser.id,
  {
    connectionId: connection.id,
    socialMedia: "THREADS",
    postType: "IMAGE",
    text: "Our launch is live",
    files: [
      {
        id: media.fileId,
        filename,
        mimetype,
        size,
        s3Prefix: media.s3Prefix,
        fileSrc: media.fileSrc,
      },
    ],
  },
  { idempotencyKey: "customer_123:post_458" },
);
```

En los vídeos, incluye `duration` en segundos al solicitar la URL y al adjuntar
el archivo. Las URL de subida son temporales; solicita una nueva si una subida ha caducado.

## Estado de la publicación

La respuesta de creación confirma que la publicación fue aceptada y puesta en cola; no
garantiza que la red social la haya publicado. Usa `post.status`, consulta periódicamente
`posts.get` o suscríbete a los webhooks `post.published` y `post.failed` para obtener el
resultado final.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.