Docs

API REST

Crea, programa y sigue publicaciones en tus cuentas conectadas de LinkedIn y X desde un servidor, con una clave de API. Cinco endpoints: crear, consultar, listar y eliminar publicaciones, y listar cuentas.

Versiónv1AutenticaciónClave de APILímite10.000/día
https://antwork.io/api/v1
01

Autenticación

4 permisos

Cada petición lleva una clave de API como bearer token. Las claves son para servidores. Si lo que quieres es conectar un asistente en vez de escribir código, usa el servidor MCP: se autentica en el navegador y no necesita ninguna clave.

Obtener una clave

Se crea desde los ajustes de tu cuenta. La clave completa se muestra una sola vez, al crearla, y después no se puede recuperar porque solo se guarda su hash. Si la pierdes, crea otra.

Authorization
Authorization: Bearer ak_a1b2c3d4e5f6a7b8_<secret>

Las claves tienen la forma ak_<id>_<secreto>. La parte <id> es pública e identifica la clave en tus ajustes; la parte secreta es la que nunca debe acabar en un repositorio, en un log ni en un navegador.

Una clave revocada deja de funcionar al instante en todos los servidores salvo en uno que la haya usado en el último minuto, que mantiene una caché corta. Revoca y rota, en vez de esperar.

Permisos

Una clave lleva permisos. write, publish y media implican read. write y publish son independientes: crear un borrador necesita write, y crear una publicación que de verdad se enviará necesita publish. Las claves creadas desde ajustes llevan los cuatro permisos; todavía no se pueden restringir ahí.

PermisoPermite
readLeer publicaciones y cuentas conectadas.
writeCrear borradores y eliminar o cancelar publicaciones.
publishCrear una publicación que saldrá de verdad, ya o programada. Basta por sí solo.
mediaReservado para endpoints de medios. Ningún endpoint lo comprueba todavía, así que concederlo no cambia nada hoy.
02

Crear publicaciones

POST /v1/posts

Una petición crea una publicación por cada cuenta de destino. Cada una es independiente, con su propia programación y su propio resultado; solo comparten un id de campaña.

Request
curl https://antwork.io/api/v1/posts \
  -H "Authorization: Bearer $ANTWORK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "accounts": ["acc_linkedin", "acc_x"],
    "text": "Shipped the API today.",
    "scheduledFor": "2026-10-01T09:00:00Z"
  }'

Cuerpo de la petición

CampoSignificado
accountsObligatorio. Ids de cuenta de GET /api/v1/accounts, como máximo 25. Se crea una publicación por cuenta.
textEl texto de la publicación, usado en cada cuenta que no tenga entrada en texts.
textsTexto por cuenta, indexado por id de cuenta. Sustituye a text para esa cuenta. Úsalo cuando una plataforma necesite una versión más corta.
mediaURLs de medios de Antwork, no cualquiera. Un archivo tiene que estar en tu biblioteca antes de adjuntarlo; una URL externa se rechaza con media_not_hosted en lugar de aceptarse y fallar al publicar. Todavía no se pueden subir archivos por la API.
scheduledForHora ISO 8601 de publicación, como máximo a 30 días. Omítela para publicar de inmediato.
drafttrue crea un borrador y no envía nada, y solo necesita el permiso write. Cualquier otro valor crea una publicación que se enviará, lo que necesita publish.
optionsAjustes específicos de cada plataforma, indexados por plataforma. Consulta Opciones por plataforma.
workspaceIdEl espacio de trabajo desde el que publicar. Solo es obligatorio si tienes más de un espacio de trabajo: sin él la petición se rechaza con workspace_required. Todas las cuentas deben pertenecer a él.
campaignIdAgrupa las publicaciones bajo un id. Se asigna solo cuando se acepta más de una cuenta; pasa un id existente para añadir estas publicaciones a ese grupo.
La API publica en cuentas de LinkedIn y X (Twitter). Una cuenta de cualquier otra plataforma se rechaza por separado con platform_not_available, y el resto de la petición sigue adelante. GET /api/v1/accounts lista todas las cuentas conectadas, así que comprueba platform antes de enviar.

La respuesta es 202 Accepted, nunca 200. Nada se publica dentro de la petición: la publicación se encola y un worker la envía, así que la respuesta dice qué se ha aceptado, no qué se ha publicado.

202 Accepted
{
  "object": "post_batch",
  "campaignId": "b3f1...",
  "posts": [
    {
      "object": "post_result",
      "id": "pQ7x...",
      "accountId": "acc_linkedin",
      "platform": "linkedin",
      "status": "accepted",
      "reason": null,
      "message": null
    },
    {
      "object": "post_result",
      "id": null,
      "accountId": "acc_x",
      "platform": "x",
      "status": "rejected",
      "reason": "text_too_long",
      "message": "@antwork: Text exceeds x character limit"
    }
  ]
}

Qué significa cada estado

  • accepted — creada y programada (o guardada, si es un borrador). Consulta el id para ver qué pasa.
  • rejected — rechazada antes de escribir nada. No existe; corrige reason y vuelve a enviar.
  • failed — se creó pero no se pudo programar. Existe y no va a salir.
Un destino falla solo. Una cuenta que se pasa del límite de caracteres no cancela las demás, así que un 202 puede contener rechazos. Lee todas las entradas de posts, no solo el código de estado. Solo cuando no se acepta ninguna la respuesta es un 400, y el array viaja igualmente con ella.

Programación

Omite scheduledFor para publicar de inmediato. Indica una hora ISO 8601 para programar, como máximo a 30 días. La cola que hay detrás no acepta tareas más lejanas, y el error indica la última hora que admite. Una hora en el pasado se rechaza con scheduled_for_in_past.

03

Consultar una publicación

GET /v1/posts/{id}

La llamada de creación devuelve ids; aquí es donde ves qué ha sido de ellos. Consulta en vez de esperar en la petición de creación, que responde mucho antes de que la plataforma conteste.

200 OK
{
  "object": "post",
  "id": "pQ7x...",
  "workspaceId": "ws_...",
  "accountId": "acc_linkedin",
  "platform": "linkedin",
  "campaignId": "b3f1...",
  "status": "published",
  "text": "Shipped the API today.",
  "mediaUrls": [],
  "scheduledFor": "2026-10-01T09:00:00.000Z",
  "publishedAt": "2026-10-01T09:00:04.000Z",
  "publishedUrl": "https://www.linkedin.com/feed/update/...",
  "platformPostId": "urn:li:share:...",
  "error": null,
  "createdAt": "2026-09-22T10:00:00.000Z",
  "updatedAt": "2026-10-01T09:00:04.000Z"
}

Una vez ha salido, se rellenan publishedUrl y platformPostId. Si ha fallado, error.message dice qué contestó la plataforma y error.advice qué hacer al respecto.

Una publicación que no existe, es de otra persona o se ha eliminado responde 404 con post_not_found. Necesita el permiso read.

Estados de una publicación

  • draft — guardada, sin programar. No se enviará.
  • scheduled — esperando su hora, o enviándose ahora mismo.
  • published — publicada en la plataforma. publishedUrl y platformPostId están rellenos.
  • failed — no se publicó. error explica por qué.

Listar publicaciones

GET /api/v1/posts es la vía de recuperación: la única otra forma de llegar a una publicación es el id que devolvió la creación. De la más reciente a la más antigua, en todos tus espacios de trabajo. Filtro opcional status (uno de los cuatro de arriba), limit de 1 a 100 (por defecto 25) y cursor con el nextCursor de la página anterior. Un nextCursor nulo significa que no hay más.

GET /v1/posts
curl "https://antwork.io/api/v1/posts?status=scheduled&limit=25" \
  -H "Authorization: Bearer $ANTWORK_API_KEY"

{ "object": "list", "posts": [ ... ], "nextCursor": "MTc5MDA3..." }
04

Listar cuentas

GET /v1/accounts

La primera llamada de cualquier integración, porque crear una publicación requiere ids de cuenta y no hay otra forma de conocerlos.

200 OK
{
  "object": "list",
  "accounts": [
    {
      "object": "account",
      "id": "acc_linkedin",
      "workspaceId": "ws_...",
      "platform": "linkedin",
      "name": "Iker on LinkedIn",
      "handle": "iker",
      "accountType": "personal",
      "active": true,
      "tokenHealth": "healthy",
      "connectedAt": "2026-01-05T09:00:00.000Z"
    }
  ]
}

Filtra con ?workspaceId= o ?platform=.

La lista incluye todas las cuentas conectadas, también de plataformas en las que la API aún no puede publicar. Solo las cuentas de LinkedIn y X (Twitter) sirven en accounts al crear una publicación.

Conviene mirar tokenHealth antes de publicar. Una conexión que necesita reautorizarse falla en el momento de publicar, que puede ser días después de la petición que la programó.
05

Cancelar y borrar

DELETE /v1/posts/{id}

DELETE /api/v1/posts/{id} cancela una publicación programada o elimina un borrador. Una publicación ya publicada se borra de forma lógica para conservar su histórico de engagement, y en cualquier caso desaparece de todas las lecturas de esta API. Necesita el permiso write.

La publicación en la plataforma se queda como está salvo que lo pidas. ?deleteFromPlatform=true encola además el borrado de la publicación en vivo, que es irreversible y visible para otras personas. Quitar una publicación de Antwork y borrarla de LinkedIn son intenciones distintas, así que la API no lo adivina.

200 OK
{
  "object": "post_deleted",
  "id": "pQ7x...",
  "softDeleted": true,
  "platformDeletionQueuedFor": ["linkedin"]
}
softDeleted: true en la respuesta significa que el documento sobrevive para analítica, no que la publicación siga visible. platformDeletionQueuedFor lista las plataformas para las que se encoló un borrado, que ocurre en segundo plano igual que la publicación.
06

Opciones por plataforma

Todo lo específico de una plataforma va en options, indexado por plataforma y aplicado a todas las cuentas de esa plataforma en la petición. Solo las plataformas de esta tabla aceptan opciones por la API.

PlataformaAcepta
linkedinno acepta opciones
xcommunityId, shareWithFollowers
options
{
  "accounts": ["acc_x"],
  "text": "Shipped the API today.",
  "options": {
    "x": { "communityId": "1493446837214", "shareWithFollowers": true }
  }
}
Las claves desconocidas se rechazan, no se ignoran. Una errata es un 400 que nombra el campo, no una publicación que sale sin el ajuste que pediste.
07

Idempotencia

Idempotency-Key

Envía una cabecera Idempotency-Key en cada creación. Sin ella, un timeout de red seguido del reintento que tu cliente HTTP hace por su cuenta produce una segunda publicación.

La clave se recuerda 24 horas, asociada a tu cuenta y al cuerpo exacto de la petición.

  • Misma clave, mismo cuerpo, ya terminada: se devuelve la respuesta original y no se crea nada nuevo.
  • Misma clave mientras la primera petición sigue en curso: 409. Reintenta en un momento.
  • Misma clave, cuerpo distinto: 422. Devolver la primera respuesta para otra petición sería peor que rechazarla.
Solo se recuerda una creación completada. Una petición rechazada por validación no, así que corregir el cuerpo y reenviarlo con la misma clave funciona.
08

Límites de uso

10.000/día

Cada clave permite 10.000 peticiones al día y 120 por minuto. Los topes existen para frenar un bucle descontrolado, no para racionar el uso normal. Si te acercas a alguno, escríbenos en vez de sortearlo.

Headers
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9812
X-RateLimit-Reset: 1790035200
Retry-After: 37

Todas las respuestas llevan el presupuesto actual, no solo las rechazadas, así que nunca hace falta agotar el límite para conocerlo. X-RateLimit-Reset es un timestamp Unix; Retry-After solo aparece en un 429 y va en segundos.

Las peticiones se cuentan pero no se facturan. Antwork cobra por cuenta conectada, no por llamada, así que esto es un tope de uso razonable y no un contador de facturación.
09

Errores

Todos los fallos tienen la misma forma. type es la clase sobre la que ramificar, code es el identificador estable del problema concreto y param nombra el campo culpable cuando lo hay. Trata message como texto para una persona leyendo un log: puede cambiar.

4xx / 5xx
{
  "error": {
    "type": "invalid_request_error",
    "code": "scheduled_for_too_far",
    "message": "Posts can be scheduled at most 30 days ahead. The latest accepted time is 2026-10-22T10:00:00.000Z.",
    "param": "scheduledFor"
  }
}
TipoSignifica
authentication_errorLa clave falta, está mal formada, no existe o está revocada. Siempre 401; code indica cuál.
permission_errorLa clave es válida pero le falta el permiso, o la cuenta detrás no tiene suscripción activa. 403.
invalid_request_errorAlgo de la petición está mal. 400, o 404 para una publicación que no existe en tu cuenta.
rate_limit_errorSe alcanzó un tope. 429, con Retry-After.
api_errorAlgo se rompió de nuestro lado. 500. Se puede reintentar con la misma clave de idempotencia.

Ramifica sobre code, nunca sobre message. Los códigos son parte del contrato; las frases no.

Códigos de error

CódigoEstado y significado
api_key_missing401 — falta la cabecera Authorization: Bearer.
api_key_malformed401 — el valor no tiene forma de clave de Antwork.
api_key_unknown401 — no existe ninguna clave con este id y secreto.
api_key_revoked401 — la clave se revocó en ajustes.
insufficient_scope403 — la clave no tiene el permiso que necesita esta llamada.
subscription_inactive403 — la cuenta de la clave no tiene una suscripción activa.
invalid_body400 — el cuerpo no es un objeto JSON.
accounts_required400 — falta accounts o está vacío.
too_many_accounts400 — más cuentas de las que admite una petición.
invalid_text400text no es una cadena.
invalid_texts400texts no es un objeto de cadenas indexado por id de cuenta.
invalid_media400media no es un array de cadenas.
media_not_hosted400 — una URL de media no está en tu biblioteca de Antwork.
invalid_scheduled_for400scheduledFor no es una hora ISO 8601 válida.
scheduled_for_in_past400scheduledFor está en el pasado.
scheduled_for_too_far400scheduledFor supera el horizonte de programación.
workspace_required400 — tienes varios espacios de trabajo y no enviaste workspaceId.
workspace_not_found400workspaceId no es un espacio de trabajo tuyo.
invalid_option400 — una clave de options es desconocida, tiene un tipo incorrecto o es de una plataforma que no está en la petición.
no_targets_accepted400 — no se aceptó ninguna cuenta y ninguna dio un motivo más concreto.
invalid_status400 — el filtro status no es uno de los cuatro estados.
invalid_limit400limit no es un número entero dentro del rango.
invalid_cursor400cursor no lo emitió esta API.
post_not_found404 — no existe esa publicación en tu cuenta.
idempotency_in_flight409 — una petición con esta Idempotency-Key sigue en curso.
idempotency_key_reused422 — esta Idempotency-Key se usó con otro cuerpo.
rate_limit_burst429 — por encima del límite por minuto.
rate_limit_daily429 — por encima del límite diario.
internal_error500 — algo falló por nuestra parte.

Cuando no se acepta ninguna cuenta de una petición de creación, la respuesta es un 400 cuyo code es el motivo de rechazo de la primera cuenta (ver la tabla siguiente), con el array posts completo al lado.

Por qué se rechazó una cuenta

El reason de una entrada rejected o failed en la respuesta de creación.

CódigoEstado y significado
account_unresolvedEl id no es una cuenta conectada en este espacio de trabajo.
platform_not_availableLa cuenta es de una plataforma en la que la API aún no publica.
text_emptyNo hay texto para esta cuenta y la plataforma lo necesita.
text_too_longEl texto supera el límite de caracteres de la plataforma.
media_requiredLa plataforma necesita una imagen o un vídeo y no se adjuntó ninguno.
unsupported_mediaLa plataforma no acepta uno de los tipos de archivo adjuntos.
video_too_longEl vídeo es más largo de lo que permite la plataforma.
token_invalidLa conexión de la cuenta ha caducado. Vuelve a conectarla en Antwork.
token_refresh_failedNo se pudo renovar la conexión. Vuelve a conectarla en Antwork.
quota_exceededHas agotado las publicaciones de tu plan en este ciclo.
schedule_failedLa publicación se creó pero no se pudo poner en cola (failed). Existe y no se enviará.