This is the abridged developer documentation for Marsial
# Construye con la API de Marsial
> Una integración para conectar cuentas sociales y publicar, programar y responder en todas tus redes. Con los mismos perfiles, cuentas y publicaciones que ves en el panel.
## Elige tu camino [Sección titulada «Elige tu camino»](#elige-tu-camino) En tu producto, con la API Tus clientes conectan sus redes desde tu app y tú publicas por ellos con una petición. Empieza por el [inicio rápido](/quickstart/) y la [autenticación](/authentication/). Desde el panel Escribe, programa, aprueba y responde desde [app.marsial.dev](https://app.marsial.dev). Las [guías](/guides/posting/) explican cada opción, también lo que hace la API por debajo. ## Lo que cubre [Sección titulada «Lo que cubre»](#lo-que-cubre) [Conectar cuentas](/guides/connecting-accounts/)El flujo OAuth en tu app, con tu marca, y cómo elegir página, organización o tablero. [Publicar y programar](/guides/posting/)Ahora, a una hora, en la cola o como borrador. Una red o todas, con opciones por red. [Comentarios y menciones](/guides/inbox/)Lee y responde los comentarios de tus publicaciones y a quien te menciona. [Analíticas](/guides/analytics/)Seguidores, interacciones por día, mejores horas y publicaciones con mejores resultados. [Webhooks](/webhooks/)Entérate al momento de lo que se publica, falla o se conecta, con firma verificable. [Para agentes de IA](/ai/)llms.txt con toda la documentación en texto, listo para tu agente o tu editor.
# Agentes de IA
> Conecta Claude, Cursor o ChatGPT a Marsial por MCP, y la documentación en texto plano para tu agente.
## Servidor MCP [Sección titulada «Servidor MCP»](#servidor-mcp) Marsial tiene un servidor [MCP](https://modelcontextprotocol.io) para que Claude, Cursor, ChatGPT y cualquier agente compatible publiquen, contesten y lean analíticas por ti, sin escribir código. **Dirección:** `https://api.marsial.dev/mcp` * Claude Code
```bash
claude mcp add --transport http marsial https://api.marsial.dev/mcp
```
Luego, en Claude Code, `/mcp` y elige `marsial` para iniciar sesión. * Cursor En `.cursor/mcp.json`:
```json
{
"mcpServers": {
"marsial": { "url": "https://api.marsial.dev/mcp" }
}
}
```
* Otros Añade un servidor MCP remoto (HTTP) con la dirección `https://api.marsial.dev/mcp`. En ChatGPT y Claude.ai es un “conector personalizado”. La primera vez, el agente abre el navegador: inicias sesión en Marsial y le das permiso. A partir de ahí actúa **en tu nombre, en tu espacio de trabajo y con tus permisos** (un miembro no puede hacer lo que su rol no permite). Lo desconectas cuando quieras en el panel, en **Desarrolladores → Agentes IA**. Las herramientas de automatización que solo envían cabeceras (n8n, Make) pueden usar una [clave API](/authentication/) en `Authorization: Bearer` en lugar de iniciar sesión. ### Qué puede hacer [Sección titulada «Qué puede hacer»](#qué-puede-hacer) | Herramienta | Para | | --------------------------------------------------------------------- | ----------------------------------------------------------------- | | `list_profiles`, `list_accounts` | Saber qué perfiles y cuentas hay. | | `create_post`, `list_posts`, `get_post`, `cancel_post`, `delete_post` | Publicar, programar, dejar en borrador o en la cola, y seguirlas. | | `list_commented_posts`, `list_comments`, `reply_to_comment` | Leer y responder comentarios. | | `list_conversations`, `list_messages`, `send_message` | Mensajes directos. | | `list_reviews`, `reply_to_review` | Reseñas de Google Business y Facebook. | | `get_followers`, `get_top_posts` | Analíticas. | | `list_blogs`, `list_articles`, `create_article` | Artículos en WordPress, Shopify, Wix y Webflow. | ## Documentación para el agente [Sección titulada «Documentación para el agente»](#documentación-para-el-agente) Toda esta documentación existe también en texto plano, pensada para modelos de lenguaje: * [`/llms.txt`](/llms.txt): el índice, con un resumen de cada página. * [`/llms-full.txt`](/llms-full.txt): toda la documentación en un solo archivo. * [`/llms-small.txt`](/llms-small.txt): una versión compacta, para contextos pequeños. Pásale una de ellas a tu agente (o pega la URL en Cursor, Claude o ChatGPT) junto con el [documento OpenAPI](https://api.marsial.dev/openapi.json) y podrá escribir la integración con los nombres, campos y errores reales. ## Buenas prácticas con agentes [Sección titulada «Buenas prácticas con agentes»](#buenas-prácticas-con-agentes) * Dale una clave API de un espacio de trabajo de pruebas, no la de producción. * Pídele que trate el `code` de los [errores](/errors/), no el texto del mensaje. * Para publicar en nombre de tus clientes, que cree un [perfil](/concepts/#perfiles) por cliente y guarde su `externalId`.
# Autenticación
> Cómo autenticar las peticiones a la API de Marsial con claves API.
Todas las peticiones a `/v1` llevan tu clave API en la cabecera `Authorization`:
```http
Authorization: Bearer marsial_live_…
```
## Crear y revocar keys [Sección titulada «Crear y revocar keys»](#crear-y-revocar-keys) * Créalas en el [panel](https://app.marsial.dev), en **Desarrolladores → Claves API**. El secreto completo se muestra una sola vez; después solo verás su prefijo. * Crea una por entorno o servicio (`producción`, `staging`…) para revocarlas por separado. * Revocar una key la invalida al instante. * Por seguridad, las keys no pueden crear ni revocar otras keys: eso solo se hace desde el panel. ## Buenas prácticas [Sección titulada «Buenas prácticas»](#buenas-prácticas) * Úsala solo desde tu servidor. Nunca en una app móvil ni en el navegador. * Guárdala en un gestor de secretos o en una variable de entorno, no en el código. * Si se filtra, revócala y crea otra. ## Workspace [Sección titulada «Workspace»](#workspace) Cada key pertenece a un workspace: todo lo que crea (perfiles, cuentas, publicaciones) es de ese workspace. Comprueba con qué workspace llamas: * curl
```bash
curl "https://api.marsial.dev/v1/me" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/me', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/me",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
# Saldo y facturación
> Cómo se cobra Marsial (prepago), qué cuesta cada cuenta y qué pasa cuando se acaba el saldo.
Marsial empieza con una **prueba gratis** y después es de **prepago**: añades saldo y se descuenta según lo usas. Nunca pagas más de lo que has cargado y no hay suscripciones que cancelar. ## Prueba gratis [Sección titulada «Prueba gratis»](#prueba-gratis) Toda cuenta nueva entra en prueba: conecta las redes que quieras y publica sin pagar. * Los **7 días** empiezan a contar con tu **primera publicación** (cuando un post sale publicado en cualquier red), no al registrarte. * Como máximo, la prueba dura **14 días desde el registro**: si en ese tiempo no publicas nada, termina igualmente. * **X** y los **números de teléfono** no entran en la prueba: necesitan saldo desde el principio. * La prueba cubre **hasta 20 cuentas**. Conectar la 21.ª pide saldo, y la primera recarga termina la prueba. * Al terminar sin haber añadido saldo, tus **publicaciones programadas se pausan** (estado `paused`) y no puedes publicar ni conectar cuentas. **No se borra nada.** * La **primera recarga** termina la prueba: las publicaciones en pausa con fecha por delante vuelven a programarse solas; las que ya pasaron esperan a que les pongas otra fecha. Te avisamos en el panel (y por email): cuando publicas por primera vez, el día antes de que se pausen tus posts y al terminar. `GET /v1/billing` trae la prueba en `trial` (estado, fin, días que quedan). ## Qué se cobra [Sección titulada «Qué se cobra»](#qué-se-cobra) **Las cuentas conectadas**, día a día y por tramos: | Cuentas | Precio por cuenta y mes | | ------------ | ----------------------- | | 1 a 10 | 6,00 € | | 11 a 100 | 3,00 € | | Desde la 101 | 1,00 € | Una cuenta se paga solo los días que está conectada: el precio mensual se reparte por días. Con 4 cuentas pagas 4 × 6 € = 24 € al mes, unos 0,77 € al día. Los impuestos van aparte. **El uso**, aparte: llamadas a la API de X, mensajes por encima de los incluidos, números de teléfono (al mes), llamadas (por minuto) y SMS (por segmento), a las tarifas de [marsial.dev/precios](https://marsial.dev/precios) y sin margen. Se descuenta cada 15 minutos. ## Añadir saldo [Sección titulada «Añadir saldo»](#añadir-saldo) Desde el panel, en Ajustes → Facturación. El pago se hace con Stripe; cada recarga va de 10 € a 500 € en las tres primeras y hasta 5.000 € después. Puedes activar la **recarga automática**: cuando el saldo baja de un importe, se recarga tu tarjeta guardada, con un máximo al mes. En la API, el saldo (`GET /v1/billing`) y los movimientos (`GET /v1/billing/movements`) van en **céntimos de euro**, con hasta tres decimales: un movimiento de `-9.678` son 0,09678 €. Cada movimiento lleva `currency: "eur"`. ## Cuando se acaba [Sección titulada «Cuando se acaba»](#cuando-se-acaba) Con el saldo a cero, tus cuentas quedan en pausa: no pueden publicar ni enviar respuestas hasta que añadas saldo. Lo que ya estaba programado sale igualmente. En la API, lo que necesita saldo responde `402`, también conectar una cuenta sin saldo o publicar cuando la prueba ha terminado: 402 Payment Required
```json
{
"error": {
"code": "payment_required",
"message": "Your free trial has ended: add balance in Billing to keep publishing. Nothing was deleted."
}
}
```
# Novedades
> Lo nuevo en la API y el panel de Marsial.
## 26 de octubre de 2026 [Sección titulada «26 de octubre de 2026»](#26-de-octubre-de-2026) * **Prueba gratis**: cubre hasta 20 cuentas; la 21.ª necesita saldo (`trial.maxAccounts`). * **Webhooks de prueba**: `POST /v1/webhook-endpoint/test` envía un ejemplo de cualquier evento con `test: true`. * **Saldo**: los movimientos llevan `currency: "eur"`; los importes son céntimos de euro. * `GET /v1/phone-numbers` sin `profileId` lista los números de todos los perfiles. Editar una copia publicada cambia el texto de la publicación; las demás copias conservan el suyo. * **Webhooks de publicaciones**: cada estado se avisa una vez, también `post.scheduled` y `post.published` cuando la red no manda nada, y `post.failed` cuando una red falla sola. Borrar una publicación con copias publicadas manda `post.removed` y después `post.deleted`. * **Estado `removed`**: una publicación retirada de todas las redes queda `removed` (antes, `cancelled`). * **Bandeja**: los ids de conversación llevan su cuenta, así que leer, responder, marcar como leída y archivar ya no piden `accountId`. Responder devuelve `201` con el `id` del mensaje. * **Cuentas**: `GET /v1/accounts/{id}` y `GET /v1/accounts/{id}/health`. Los sitios, los CRM y las conexiones de anuncios dicen `canPost: false`. Al volver de conectar, la URL lleva el `profileId`. * **Llamadas**: `GET /v1/calls/estimate` acepta `numberId` y dice si ese número puede llegar al destino. * `GET /v1/posts?profileId=` con un perfil que no existe responde `404`. * **Prueba gratis de 7 días**: sustituye a las 2 cuentas gratis. Los 7 días empiezan con la primera publicación (14 días como máximo desde el registro); al terminar sin recarga, las publicaciones programadas pasan a `paused` hasta la primera recarga. `GET /v1/billing` trae la prueba en `trial`. Ver [Saldo y facturación](/billing/#prueba-gratis). * **Precios**: todas las cuentas conectadas se cobran desde la primera (6 € las 10 primeras). ## 25 de octubre de 2026 [Sección titulada «25 de octubre de 2026»](#25-de-octubre-de-2026) * **Anuncios**: conecta Meta, Google, LinkedIn, TikTok, Pinterest, X y Reddit Ads; consulta campañas con su gasto y resultados, páusalas, cambia presupuestos, promociona publicaciones (`POST /v1/posts/{id}/boost`), crea campañas y envía conversiones. En el panel, la sección Anuncios. Ver [Anuncios](/guides/ads/). * **Aprobación de anuncios**: con `requireAdsApproval`, los cambios que gastan dinero pedidos por miembros o agentes de IA esperan a un propietario o admin (`/v1/ads/requests`). Ver [Aprobación de cambios](/guides/ads/#aprobaci%C3%B3n-de-cambios). * **Números, llamadas y SMS**: compra números en 67 países (con KYC propio donde el país lo pide), desvía las llamadas a tu móvil o a tu agente de voz, con buzón, horario, grabación y transcripción; llama desde tu número y envía SMS cuyas respuestas llegan a la bandeja. En el panel, la sección Teléfono. Ver [Números, llamadas y SMS](/guides/phone/). * **WhatsApp Business**: conecta tu número, crea plantillas, escribe primero con una plantilla aprobada (`POST /v1/inbox/conversations`) y envía difusiones programadas. En el panel, Bandeja → WhatsApp. Ver [WhatsApp](/guides/whatsapp/). * **Slack y HubSpot**: publica en canales de Slack y responde a sus DMs desde la bandeja; HubSpot recibe como contactos a quien escribe a tu bandeja, con sus mensajes (`/v1/accounts/{id}/crm-settings`). * **Servidor MCP**: Claude, Cursor, ChatGPT y otros agentes se conectan a `https://api.marsial.dev/mcp` iniciando sesión en Marsial, y publican, responden y leen analíticas con tus permisos. Se gestionan en el panel, en Desarrolladores → Agentes IA. Ver [Agentes de IA](/ai/). * **Blogs**: conecta WordPress (WordPress.com o autoalojado), Shopify, Wix y Webflow y escribe, programa y publica sus artículos con `/v1/accounts/{id}/blogs`. En el panel, la pestaña Blog de Publicaciones. Ver [Blogs](/guides/blogs/). * **Mensajes directos y reseñas** en la bandeja: conversaciones de Instagram, Facebook, X, Bluesky y Telegram, y reseñas de Google Business y Facebook, con los eventos `message.received` y `review.received`. * **Comentario a mensaje privado**: las automatizaciones de Instagram y Facebook pueden contestar por privado (`dmMessage`, `buttons`), y las de Instagram, a quien responde a una historia. * **Cinco redes más**: Bluesky, Reddit, Snapchat, Telegram y Discord. * **Menciones en la bandeja**: `GET /v1/inbox/mentions` lista quién etiqueta a tus cuentas de Instagram y a tus páginas de LinkedIn, y `POST /v1/inbox/mentions/{id}/reply` responde a las de Instagram. En el panel, la pestaña Menciones de la Bandeja. * **Nueva documentación** en docs.marsial.dev, con la referencia completa por secciones, ejemplos en curl, Node y Python, y `llms.txt` para agentes. * **Panel renovado**: pantalla Hoy, menú por secciones y paleta nueva. ## 24 de octubre de 2026 [Sección titulada «24 de octubre de 2026»](#24-de-octubre-de-2026) * **Saldo prepago**: Marsial pasa a cobrarse con saldo; las cuentas se descuentan día a día y el uso cada 15 minutos. Lo que necesita saldo responde `402 payment_required`. * **Reciclar publicaciones**: `PUT /v1/posts/{id}/recycling` y el evento `post.recycled`. * **Aprobación de publicaciones**: el estado `pending_approval`, `POST /v1/posts/{id}/review` y el evento `post.rejected`. * **Entrar con Google** en el panel. ## 23 de octubre de 2026 [Sección titulada «23 de octubre de 2026»](#23-de-octubre-de-2026) * **Equipos**: miembros, roles e invitaciones. * **Bandeja y analíticas** por perfil y por cuenta. * **Automatizaciones** de respuesta a comentarios. * **Editar publicaciones**, métricas por publicación, grupos de cuentas e importación desde CSV. * **Opciones para cada red**, multimedia propia por destino y borradores. * **Cola de publicación** por perfil y estado de las cuentas. * **API pública** con documento OpenAPI y webhooks firmados.
# Conceptos
> Espacios de trabajo, perfiles, cuentas, publicaciones y sus estados, ids, fechas y paginación.
## Espacio de trabajo [Sección titulada «Espacio de trabajo»](#espacio-de-trabajo) Tu cuenta de Marsial es un espacio de trabajo: tiene un equipo (propietarios, admins y miembros), un saldo, sus claves API y sus webhooks. Una clave API actúa sobre todo el espacio de trabajo. Ver [Equipo y roles](/guides/team/) y [Saldo y facturación](/billing/). ## Perfiles [Sección titulada «Perfiles»](#perfiles) Un perfil (`prf_…`) es una marca o un cliente. Agrupa sus cuentas, su [cola](/guides/queue/) y su zona horaria. Si construyes una plataforma, crea un perfil por cliente y guarda tu propio id en `externalId`. Todo espacio de trabajo empieza con un perfil, «Mi marca», que se puede renombrar o borrar. ## Cuentas [Sección titulada «Cuentas»](#cuentas) Una cuenta (`acc_…`) es una cuenta social conectada a un perfil mediante el [flujo de conexión](/guides/connecting-accounts/). Su `status` dice si puede publicar: `active`, o `needs_reconnection` cuando la red retiró el permiso y hay que volver a conectarla. `GET /v1/accounts/health` comprueba las cuentas contra cada red. ## Publicaciones [Sección titulada «Publicaciones»](#publicaciones) Una publicación (`pst_…`) tiene un texto, imágenes o vídeos y uno o varios **destinos** (`targets`): las cuentas donde sale, cada una con su propio texto y sus [opciones de red](/guides/network-options/). | Estado | Qué significa | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | | `draft` | Borrador: guardada sin fecha. También una publicación rechazada en la revisión. | | `pending_approval` | Espera a que un propietario o admin la [apruebe](/guides/approval/). | | `scheduled` | Programada para `scheduledFor` (o para el siguiente hueco de la cola). | | `paused` | Estaba programada cuando terminó la [prueba gratis](/billing/#prueba-gratis) sin recarga. Vuelve a su hora con la primera recarga. | | `publishing` | Saliendo en las redes. | | `published` | Publicada en todos sus destinos. | | `partial` | Publicada en unos destinos y fallida en otros. Cada destino dice su error. | | `failed` | No salió en ningún destino. Se puede reintentar con `POST /v1/posts/{id}/retry`. | | `cancelled` | Cancelada antes de salir. | | `removed` | Salió y después se retiró de todas las redes. | | `deleted` | Borrada de Marsial. Solo aparece en el evento `post.deleted`. | Cada destino tiene su propio `status` y, cuando sale, la `url` de la publicación en esa red. ## Ids [Sección titulada «Ids»](#ids) Todos los ids son de Marsial y tienen un prefijo que dice qué son: `prf_`, `acc_`, `pst_`, `grp_` (grupos de cuentas), `cs_` (sesiones de conexión), `evt_` (eventos de webhook). Los de la bandeja (`cnv_`, `thr_`, `cmt_`, `mtn_`, `rev_`) son opacos: úsalos tal cual, sin interpretarlos. ## Fechas y zonas horarias [Sección titulada «Fechas y zonas horarias»](#fechas-y-zonas-horarias) Las fechas van en ISO 8601. Al programar, manda la hora con su desfase (`2026-10-30T09:00:00+01:00`) o una hora local con `timezone` (`Europe/Madrid`). Las respuestas devuelven UTC. ## Paginación [Sección titulada «Paginación»](#paginación) Los listados largos devuelven `nextCursor`. Pásalo como `cursor` en la siguiente petición; cuando es `null`, no hay más. Una página
```json
{
"data": {
"items": [],
"nextCursor": "eyJ…"
}
}
```
# Errores
> Códigos de error de la API y cómo tratarlos.
Los errores siempre tienen la misma forma, con un `code` estable para tu código y un `message` legible:
```json
{
"error": {
"code": "invalid_request",
"message": "targets.0.tiktok: TikTok requires consent: true"
}
}
```
| HTTP | `code` | Qué hacer | | ---- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 400 | `invalid_request` | Corrige la petición: el mensaje dice qué campo falla. | | 401 | `unauthorized` | Falta la clave API, es incorrecta o está revocada. | | 403 | `forbidden` | No tienes permiso para esa operación. | | 402 | `payment_required` | Hace falta saldo: para conectar más de 2 cuentas, o para publicar y enviar desde las cuentas a partir de la tercera o de X. Recarga en el panel, en Ajustes → Facturación. Ver [Saldo y facturación](/billing/). | | 404 | `not_found` | El recurso no existe o es de otro workspace. | | 422 | `provider_rejected` | La red rechazó la petición (formato, límites, permisos). El mensaje explica el motivo. | | 500 | `internal_error` | Fallo nuestro. Reintenta y, si sigue, escríbenos. | | 502 | `provider_unavailable` | Una red o un servicio no responde ahora. Reintenta en unos segundos. | ## Reintentar bien [Sección titulada «Reintentar bien»](#reintentar-bien) * Reintenta solo `500` y `502`, con espera creciente (1 s, 2 s, 4 s…). * No reintentes los `4xx` sin cambiar la petición. * Si una publicación ya se creó, usa `POST /v1/posts/{id}/retry` en vez de crear otra.
# Glosario
> Las palabras de Marsial, en el panel y en la API.
| Término | En la API | Qué es | | ------------------ | ---------------------------- | -------------------------------------------------------------------------- | | Espacio de trabajo | `workspace` | Tu cuenta de Marsial: equipo, saldo, claves API y webhooks. | | Perfil | `profile`, `prf_…` | Una marca o un cliente. Agrupa sus cuentas y su cola. | | Cuenta | `account`, `acc_…` | Una cuenta social conectada a un perfil. | | Grupo de cuentas | `account-group`, `grp_…` | Una selección de cuentas guardada para publicar en ellas de una vez. | | Publicación | `post`, `pst_…` | Lo que se publica: texto, imágenes o vídeos y sus destinos. | | Destino | `target` | Una cuenta donde sale una publicación, con su texto y opciones. | | Cola | `queue` | Las horas fijas de cada semana de un perfil. | | Reciclar | `recycling` | Volver a publicar una publicación cada cierto tiempo. | | Aprobación | `pending_approval`, `review` | La revisión de un propietario o admin antes de publicar. | | Bandeja | `inbox` | Comentarios y menciones de las cuentas de un perfil. | | Mención | `mention`, `mtn_…` | Una publicación o un comentario de otra persona que etiqueta a tu cuenta. | | Automatización | `automation` | Una respuesta automática a quien comenta una palabra clave. | | Saldo | `billing` | El dinero cargado en el espacio de trabajo, que se descuenta según el uso. | | Clave API | `api-key` | La credencial para llamar a la API desde tu servidor. | | Webhook | `webhooks` | El aviso que Marsial envía a tu servidor cuando pasa algo. |
# Anuncios
> Campañas en Meta, Google, LinkedIn, TikTok, Pinterest, X y Reddit: resultados, pausas, presupuestos, promocionar publicaciones y conversiones.
Los anuncios van por una **conexión de anuncios**: una cuenta más del perfil, con plataforma `meta-ads`, `google-ads`, `linkedin-ads`, `tiktok-ads`, `pinterest-ads`, `x-ads` o `reddit-ads`. No publica: llega a una o varias **cuentas publicitarias** de la red, que son las que pagan. ## Conectar [Sección titulada «Conectar»](#conectar) `GET /v1/connect/meta-ads` (o la plataforma que toque) y mandar al usuario a la URL, como cualquier [conexión](/guides/connecting-accounts/): * **Meta** usa el inicio de sesión para empresas de Meta: no crea ninguna cuenta de Facebook para publicar. Quien conecta debe ser administrador del portfolio empresarial. * **LinkedIn, TikTok, Pinterest y Google**: si la cuenta social del perfil ya dio permiso de anuncios, vuelve al momento sin pedir nada. * **X Ads** cuelga de la cuenta de X del perfil: conéctala antes. Luego lista sus cuentas publicitarias. Su `id` es el `adAccountId` del resto de llamadas. * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_ads123/ads/ad-accounts" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_ads123/ads/ad-accounts', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_ads123/ads/ad-accounts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Resultados y control [Sección titulada «Resultados y control»](#resultados-y-control) * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns?from=2026-10-01&to=2026-10-31" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns?from=2026-10-01&to=2026-10-31', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns?from=2026-10-01&to=2026-10-31",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Devuelve las campañas (también las creadas en el administrador de anuncios de la red) con gasto, impresiones, clics, alcance y conversiones del periodo. Para pausar, reanudar o cambiar el presupuesto: * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns/120210000000" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "paused",
"budget": {
"amount": 25,
"type": "daily"
}
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns/120210000000', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"status": "paused",
"budget": {
"amount": 25,
"type": "daily"
}
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns/120210000000",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"status": "paused",
"budget": {
"amount": 25,
"type": "daily"
}
},
)
data = res.json()["data"]
```
## Promocionar una publicación [Sección titulada «Promocionar una publicación»](#promocionar-una-publicación) Convierte la copia publicada de una publicación de Marsial en anuncio. `accountId` es la cuenta de esa copia (por ejemplo, el Instagram) y `adAccountId`, la cuenta publicitaria que paga. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_9f2a/boost" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"adAccountId": "act_120210",
"name": "Otoño",
"goal": "traffic",
"budget": {
"amount": 40,
"type": "daily"
},
"targeting": {
"countries": [
"ES",
"PT"
],
"ageMin": 25,
"ageMax": 45
}
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_9f2a/boost', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"adAccountId": "act_120210",
"name": "Otoño",
"goal": "traffic",
"budget": {
"amount": 40,
"type": "daily"
},
"targeting": {
"countries": [
"ES",
"PT"
],
"ageMin": 25,
"ageMax": 45
}
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_9f2a/boost",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"adAccountId": "act_120210",
"name": "Otoño",
"goal": "traffic",
"budget": {
"amount": 40,
"type": "daily"
},
"targeting": {
"countries": [
"ES",
"PT"
],
"ageMin": 25,
"ageMax": 45
}
},
)
data = res.json()["data"]
```
`goal` es lo que optimiza la red (`engagement`, `traffic`, `awareness`, `video_views`…; cada red acepta una parte). Un presupuesto `lifetime` necesita `endDate`. La red revisa el anuncio antes de mostrarlo. ## Crear campañas [Sección titulada «Crear campañas»](#crear-campañas) `POST /v1/accounts/{id}/ads/campaigns` crea campaña, grupo de anuncios y anuncio en una sola llamada, **en los términos de cada red**: `adAccountId`, `goal`, `budgetAmount`, `budgetType`, la creatividad (`headline`, `body`, `imageUrl` o `videoUrl`, `linkUrl`, `callToAction`) y la segmentación. Marsial rellena la conexión; tú no envíes `accountId`. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"adAccountId": "act_120210",
"name": "Rebajas",
"goal": "traffic",
"budgetAmount": 30,
"budgetType": "daily",
"headline": "Rebajas de invierno",
"body": "Hasta un 40% en abrigos",
"imageUrl": "https://cdn.acme.com/rebajas.jpg",
"linkUrl": "https://acme.com/rebajas",
"callToAction": "SHOP_NOW",
"targeting": {
"countries": [
"ES"
]
}
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"adAccountId": "act_120210",
"name": "Rebajas",
"goal": "traffic",
"budgetAmount": 30,
"budgetType": "daily",
"headline": "Rebajas de invierno",
"body": "Hasta un 40% en abrigos",
"imageUrl": "https://cdn.acme.com/rebajas.jpg",
"linkUrl": "https://acme.com/rebajas",
"callToAction": "SHOP_NOW",
"targeting": {
"countries": [
"ES"
]
}
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_ads123/ads/campaigns",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"adAccountId": "act_120210",
"name": "Rebajas",
"goal": "traffic",
"budgetAmount": 30,
"budgetType": "daily",
"headline": "Rebajas de invierno",
"body": "Hasta un 40% en abrigos",
"imageUrl": "https://cdn.acme.com/rebajas.jpg",
"linkUrl": "https://acme.com/rebajas",
"callToAction": "SHOP_NOW",
"targeting": {
"countries": [
"ES"
]
}
},
)
data = res.json()["data"]
```
## Conversiones [Sección titulada «Conversiones»](#conversiones) Devuelve ventas y leads a la red para que optimice mejor: la API de conversiones de Meta, las conversiones offline de Google, LinkedIn y TikTok. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_ads123/ads/conversions" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pixelId": "1234567890",
"events": [
{
"eventName": "Purchase",
"eventTime": 1793000000,
"user": {
"email": "ana@acme.com"
},
"value": 59.9,
"currency": "EUR"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_ads123/ads/conversions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"pixelId": "1234567890",
"events": [
{
"eventName": "Purchase",
"eventTime": 1793000000,
"user": {
"email": "ana@acme.com"
},
"value": 59.9,
"currency": "EUR"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_ads123/ads/conversions",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"pixelId": "1234567890",
"events": [
{
"eventName": "Purchase",
"eventTime": 1793000000,
"user": {
"email": "ana@acme.com"
},
"value": 59.9,
"currency": "EUR"
}
]
},
)
data = res.json()["data"]
```
## Aprobación de cambios [Sección titulada «Aprobación de cambios»](#aprobación-de-cambios) Si activas la aprobación de anuncios (`PATCH /v1/workspace` con `requireAdsApproval: true`, o en el panel, Ajustes → Equipo), lo que gasta dinero (reanudar, cambiar presupuestos, promocionar y crear campañas) no llega a la red cuando lo piden **miembros o agentes de IA**: la API responde `202` con la solicitud (`adr_…`, `status: "pending"`) y un propietario o admin la aprueba o la rechaza. Pausar se aplica siempre al momento, porque solo deja de gastar. Las claves API usadas en `/v1` son tu integración y no esperan; un agente que entra por el [servidor MCP](/ai/) siempre espera, aunque actúe por un propietario. * curl
```bash
curl "https://api.marsial.dev/v1/ads/requests?status=pending" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/ads/requests?status=pending', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/ads/requests?status=pending",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
- curl
```bash
curl -X POST "https://api.marsial.dev/v1/ads/requests/adr_3m8p2q/review" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "approve"
}'
```
- Node
```js
const res = await fetch('https://api.marsial.dev/v1/ads/requests/adr_3m8p2q/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"decision": "approve"
}),
});
const { data } = await res.json();
```
- Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/ads/requests/adr_3m8p2q/review",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"decision": "approve"
},
)
data = res.json()["data"]
```
Al aprobar, el cambio se envía a la red en ese momento y la solicitud queda `approved`; si la red lo rechaza, queda `failed` con el motivo en `error`. Con `reject` puedes dejar una `note` para quien lo pidió. Los agentes de IA nunca pueden aprobar. ## Lo que cuesta [Sección titulada «Lo que cuesta»](#lo-que-cuesta) El gasto en anuncios lo pagas directamente a cada red, en su cuenta publicitaria. Marsial cobra la conexión como una cuenta más y, a partir de 500 anuncios activos, cada anuncio gestionado ([tarifas](/billing/)). En el panel, la sección **Anuncios** muestra las campañas y deja pausarlas y cambiar su presupuesto; el detalle de una publicación publicada tiene el botón para promocionarla. Los agentes de IA pueden hacer lo mismo por el [servidor MCP](/ai/).
# Analíticas por cuenta
> Seguidores, totales diarios, mejores horas para publicar y mejores publicaciones de cada cuenta.
Todo se pide por perfil y, si quieres, por una cuenta. Las fechas van en `YYYY-MM-DD`; por defecto, los últimos 30 días. ## Seguidores [Sección titulada «Seguidores»](#seguidores) * curl
```bash
curl "https://api.marsial.dev/v1/analytics/followers?profileId=prf_8f2k4d&from=2026-10-01" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/analytics/followers?profileId=prf_8f2k4d&from=2026-10-01', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/analytics/followers?profileId=prf_8f2k4d&from=2026-10-01",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Seguidores actuales, crecimiento del periodo e histórico diario de cada cuenta. Las redes los actualizan una vez al día. ## Totales diarios [Sección titulada «Totales diarios»](#totales-diarios) * curl
```bash
curl "https://api.marsial.dev/v1/analytics/daily?profileId=prf_8f2k4d&accountId=acc_3k9x2m" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/analytics/daily?profileId=prf_8f2k4d&accountId=acc_3k9x2m', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/analytics/daily?profileId=prf_8f2k4d&accountId=acc_3k9x2m",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Publicaciones e interacción de cada día, contada el día que llega (un post de hace semanas que sigue recibiendo me gusta suma en los días nuevos), y totales por red. ## Mejores horas [Sección titulada «Mejores horas»](#mejores-horas) * curl
```bash
curl "https://api.marsial.dev/v1/analytics/best-times?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/analytics/best-times?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/analytics/best-times?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Interacción media por día de la semana (`0` domingo … `6` sábado) y hora en UTC, de mejor a peor. Conviértelas a la zona horaria de tu usuario antes de mostrarlas. ## Mejores publicaciones [Sección titulada «Mejores publicaciones»](#mejores-publicaciones) * curl
```bash
curl "https://api.marsial.dev/v1/analytics/top-posts?profileId=prf_8f2k4d&limit=10" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/analytics/top-posts?profileId=prf_8f2k4d&limit=10', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/analytics/top-posts?profileId=prf_8f2k4d&limit=10",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Las publicaciones del periodo ordenadas por interacción (o por fecha con `sortBy=date`). `postId` es la publicación de Marsial si salió desde Marsial; `external: true` marca las publicadas fuera.
# Aprobación de publicaciones
> Que un propietario o admin revise las publicaciones antes de que salgan.
Con la aprobación, una publicación queda en `pending_approval` hasta que un propietario o un admin del equipo la aprueba o la rechaza. Mientras espera no sale, aunque llegue su hora. ## Cuándo se pide [Sección titulada «Cuándo se pide»](#cuándo-se-pide) * **Para todo el equipo**: activa `requireApproval` en el espacio de trabajo (en el panel, Ajustes → Equipo). Desde entonces, las publicaciones de los **miembros** esperan aprobación. * **Para una publicación concreta**: manda `requiresApproval: true` al crearla. Útil si tu producto deja que tus clientes revisen lo que publicas por ellos. - curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Sorteo: dos entradas para el concierto 🎶",
"targets": [
{
"accountId": "acc_3k9x2m"
}
],
"scheduledFor": "2026-11-05T10:00:00+01:00",
"requiresApproval": true
}'
```
- Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Sorteo: dos entradas para el concierto 🎶",
"targets": [
{
"accountId": "acc_3k9x2m"
}
],
"scheduledFor": "2026-11-05T10:00:00+01:00",
"requiresApproval": true
}),
});
const { data } = await res.json();
```
- Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Sorteo: dos entradas para el concierto 🎶",
"targets": [
{
"accountId": "acc_3k9x2m"
}
],
"scheduledFor": "2026-11-05T10:00:00+01:00",
"requiresApproval": True
},
)
data = res.json()["data"]
```
## Aprobar o rechazar [Sección titulada «Aprobar o rechazar»](#aprobar-o-rechazar) * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/review" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "reject",
"note": "Falta la fecha del concierto en el texto."
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"decision": "reject",
"note": "Falta la fecha del concierto en el texto."
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/review",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"decision": "reject",
"note": "Falta la fecha del concierto en el texto."
},
)
data = res.json()["data"]
```
- **`approve`**: la programa para su fecha, la manda a la cola o la publica ya si su fecha pasó. - **`reject`**: la devuelve a borrador con la nota en `approval.note`, para que quien la escribió la corrija. Al rechazarla se envía el webhook `post.rejected`.
# Automatizaciones
> Contesta automáticamente a quien comente una palabra clave, por mensaje privado o en público.
Una automatización vigila los comentarios de una cuenta y, cuando alguien escribe una palabra clave, le contesta por ti: con un mensaje privado (Instagram y Facebook), en público o las dos cosas. Quien comente “precio” recibe el enlace en segundos, aunque sea de madrugada. ## Crear una [Sección titulada «Crear una»](#crear-una) * curl
```bash
curl -X POST "https://api.marsial.dev/v1/automations" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"name": "Enlace de precios",
"keywords": [
"precio",
"info"
],
"matchMode": "word",
"dmMessage": "¡Hola! Aquí tienes los precios 👇",
"buttons": [
{
"type": "url",
"title": "Ver precios",
"url": "https://acme.com/precios"
}
],
"commentReply": "¡Te lo hemos mandado por privado!"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/automations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"name": "Enlace de precios",
"keywords": [
"precio",
"info"
],
"matchMode": "word",
"dmMessage": "¡Hola! Aquí tienes los precios 👇",
"buttons": [
{
"type": "url",
"title": "Ver precios",
"url": "https://acme.com/precios"
}
],
"commentReply": "¡Te lo hemos mandado por privado!"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/automations",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"name": "Enlace de precios",
"keywords": [
"precio",
"info"
],
"matchMode": "word",
"dmMessage": "¡Hola! Aquí tienes los precios 👇",
"buttons": [
{
"type": "url",
"title": "Ver precios",
"url": "https://acme.com/precios"
}
],
"commentReply": "¡Te lo hemos mandado por privado!"
},
)
data = res.json()["data"]
```
## Qué se puede hacer en cada red [Sección titulada «Qué se puede hacer en cada red»](#qué-se-puede-hacer-en-cada-red) | Red | Mensaje privado | Respuesta pública | | ----------------------------------- | ---------------------------- | ----------------- | | Instagram | Sí, y respuestas a historias | Sí | | Facebook | Sí | Sí | | TikTok, Threads, LinkedIn y YouTube | No | Sí (obligatoria) | * **`keywords`**: las palabras que la activan. Vacío: cualquier comentario. * **`matchMode`**: `contains` (contiene la palabra, también dentro de otras), `word` (la palabra suelta) o `exact` (el comentario entero). * **`postId`**: solo en una publicación de Marsial. Para una publicada fuera de Marsial, `inboxPostId` (el id de la [bandeja](/guides/inbox/)). Sin ninguno, vigila todas. * **`dmMessage`** y **`buttons`**: el mensaje privado y, opcionalmente, botones con enlace. * **`commentReply`**: la respuesta pública bajo el comentario. * **`repeat`**: `once` manda un mensaje por persona; `every_comment`, uno por comentario. * **`trigger: "story_reply"`** (Instagram): contesta por privado a quien responde a una historia, en vez de a comentarios. * **`likeComment`** y **`hideComment`**: además, dar me gusta al comentario u ocultarlo. ## Ver qué ha hecho [Sección titulada «Ver qué ha hecho»](#ver-qué-ha-hecho) Cada automatización trae sus contadores en `stats` (activaciones, mensajes enviados y fallidos, clics), y su historial dice qué comentario la activó y si el mensaje llegó: * curl
```bash
curl "https://api.marsial.dev/v1/automations/aut_6r3e9w/logs" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/automations/aut_6r3e9w/logs', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/automations/aut_6r3e9w/logs",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Para pausarla, `PATCH` con `active: false`; para borrarla, `DELETE`.
# Blogs
> Escribe, programa y publica artículos en WordPress, Shopify, Wix y Webflow con la misma API que tus redes.
Un sitio de WordPress, una tienda de Shopify o una web de Wix o Webflow se conecta a un perfil como cualquier otra cuenta (`acc_…`). La diferencia es lo que recibe: **artículos de su blog**, no publicaciones. Todo el contenido vive en el sitio; Marsial no guarda copia. ## Conectar el sitio [Sección titulada «Conectar el sitio»](#conectar-el-sitio) Wix, Webflow y WordPress.com usan el mismo flujo que las redes ([Conectar cuentas](/guides/connecting-accounts/)): `GET /v1/connect/{platform}` y mandar al usuario a la URL. **Shopify** no tiene selector de tiendas: añade `shop` con el dominio `.myshopify.com` de la tienda (o solo su prefijo). * curl
```bash
curl "https://api.marsial.dev/v1/connect/shopify?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado&shop=acme" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/shopify?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado&shop=acme', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/connect/shopify?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado&shop=acme",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
**WordPress autoalojado** no tiene OAuth. El usuario crea una contraseña de aplicación en WordPress (Usuarios → Perfil → Contraseñas de aplicación) y tu servidor la envía con su nombre de usuario. Marsial comprueba que el sitio responde y que ese usuario puede publicar y subir imágenes. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/connect/wordpress" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profileId": "prf_8f2k4d",
"siteUrl": "https://blog.acme.com",
"username": "editor",
"applicationPassword": "abcd efgh ijkl mnop qrst uvwx"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/wordpress', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"profileId": "prf_8f2k4d",
"siteUrl": "https://blog.acme.com",
"username": "editor",
"applicationPassword": "abcd efgh ijkl mnop qrst uvwx"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/connect/wordpress",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"profileId": "prf_8f2k4d",
"siteUrl": "https://blog.acme.com",
"username": "editor",
"applicationPassword": "abcd efgh ijkl mnop qrst uvwx"
},
)
data = res.json()["data"]
```
## Elegir el blog [Sección titulada «Elegir el blog»](#elegir-el-blog) Cada sitio tiene uno o más blogs. WordPress y Wix tienen uno (`1`); una tienda Shopify puede tener varios, y en Webflow cada colección del CMS con un campo de texto enriquecido es un blog. * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Escribir un artículo [Sección titulada «Escribir un artículo»](#escribir-un-artículo) Sin `isPublished`, el artículo queda en **borrador**. Con `isPublished: true` se publica al momento, o en la fecha de `publishDate` si es futura. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Llega la colección de otoño",
"bodyHtml": "Las primeras piezas llegan el mes que viene.
",
"excerpt": "Un adelanto de lo que llega.",
"tags": [
"otoño",
"novedades"
],
"image": {
"url": "https://cdn.acme.com/otono.jpg",
"altText": "Abrigos de lana"
},
"isPublished": true,
"publishDate": "2026-11-03T09:00:00+01:00"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"title": "Llega la colección de otoño",
"bodyHtml": "Las primeras piezas llegan el mes que viene.
",
"excerpt": "Un adelanto de lo que llega.",
"tags": [
"otoño",
"novedades"
],
"image": {
"url": "https://cdn.acme.com/otono.jpg",
"altText": "Abrigos de lana"
},
"isPublished": true,
"publishDate": "2026-11-03T09:00:00+01:00"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"title": "Llega la colección de otoño",
"bodyHtml": "Las primeras piezas llegan el mes que viene.
",
"excerpt": "Un adelanto de lo que llega.",
"tags": [
"otoño",
"novedades"
],
"image": {
"url": "https://cdn.acme.com/otono.jpg",
"altText": "Abrigos de lana"
},
"isPublished": True,
"publishDate": "2026-11-03T09:00:00+01:00"
},
)
data = res.json()["data"]
```
| Campo | Qué es | | ---------- | ------------------------------------------------------------------------------------------------------- | | `title` | Obligatorio al crear. | | `bodyHtml` | El artículo en HTML. | | `handle` | El slug de la URL. Si no lo envías, sale del título. En Shopify no cambia después. | | `excerpt` | Resumen para los listados. | | `tags` | Sustituye la lista entera. Las que no existan se crean. | | `author` | WordPress: id del usuario. Shopify: nombre visible. Webflow: id del elemento autor. | | `image` | Imagen destacada desde una URL pública; súbela antes con [`POST /v1/media/upload-url`](/guides/media/). | | `seo` | Título y descripción para buscadores. Solo Shopify y Wix. | | `fields` | Solo Webflow: los campos propios de la colección, por su slug. | ## Cambiar, despublicar y borrar [Sección titulada «Cambiar, despublicar y borrar»](#cambiar-despublicar-y-borrar) `PATCH` cambia solo lo que envíes. `isPublished: false` devuelve a borrador un artículo publicado o programado. * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"isPublished": false
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"isPublished": false
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"isPublished": False
},
)
data = res.json()["data"]
```
`GET /v1/accounts/{id}/blogs/{blogId}/articles` lista publicados, programados y borradores (en WordPress, también pendientes y privados), con `status` y la `url` en la web. `DELETE` lo borra también del sitio. Precaución Estas cuentas no aceptan publicaciones: `POST /v1/posts` con un sitio como destino responde `400`. En el panel, la pestaña **Blog** de Publicaciones hace lo mismo: elegir sitio y blog, escribir, programar y publicar.
# Conectar cuentas
> El flujo OAuth para conectar las cuentas sociales de tus usuarios desde tu propia app.
Tus usuarios conectan sus redes desde tu app, con tu marca. Nunca ven las credenciales ni tú tienes que guardar tokens. ## El flujo [Sección titulada «El flujo»](#el-flujo) 1. Tu servidor pide `GET /v1/connect/{platform}` con el `profileId` y la `redirectUrl` de tu app. 2. Rediriges al usuario a la `url` que devuelve. Autoriza la red con su cuenta. 3. Marsial le devuelve a tu `redirectUrl` con el resultado en la query. * curl
```bash
curl "https://api.marsial.dev/v1/connect/linkedin?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/linkedin?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/connect/linkedin?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Qué llega a tu redirectUrl [Sección titulada «Qué llega a tu redirectUrl»](#qué-llega-a-tu-redirecturl) | Resultado | Parámetros | | ------------ | ----------------------------------------------------------------------------------------------------------- | | Conectada | `connected=`, `accountId=acc_…` y, si la red lo da, `username` | | Siempre | `profileId`: el perfil al que se conectó | | Falta elegir | `select=` y `platform`. Mira el paso siguiente. | | Error | `error=`, `platform`, `error_message` e `is_user_fixable` (`true` si el usuario puede reintentarlo) | ## Elegir página, organización o tablero [Sección titulada «Elegir página, organización o tablero»](#elegir-página-organización-o-tablero) Algunas redes conectan algo concreto dentro de la cuenta del usuario. Entonces vuelve con `select` y tu app enseña la lista para que elija: | Red | Qué se elige | | --------------- | ---------------------------------------------------- | | Facebook | La página | | LinkedIn | Su perfil personal o una organización que administra | | Pinterest | El tablero por defecto | | Google Business | La ficha (ubicación) | | Snapchat | El perfil público | | Slack | El canal | | WhatsApp | El número, si la cuenta tiene varios | Bluesky y Discord no usan OAuth puro, pero no necesitas nada distinto: la pantalla de conexión de Marsial pide al usuario lo que haga falta (la contraseña de aplicación de Bluesky o el canal de Discord) y vuelve a tu `redirectUrl` con `connected`. **Slack** vuelve con `select=` para elegir el canal, como Facebook o LinkedIn; un canal privado necesita que invites antes a la app (`/invite`). Los sitios (WordPress, Shopify, Wix y Webflow) también se conectan aquí, con dos diferencias: Shopify necesita `shop` y WordPress autoalojado se conecta con `POST /v1/connect/wordpress`. Está todo en [Blogs](/guides/blogs/). ### Lista las opciones [Sección titulada «Lista las opciones»](#lista-las-opciones) * curl
```bash
curl "https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/options" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/options', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/options",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
200 OK
```json
{
"data": {
"platform": "facebook",
"options": [
{ "id": "1042…", "name": "Acme Store", "detail": "@acmestore" },
{ "id": "2210…", "name": "Acme Outlet", "detail": "Tienda de ropa" }
]
}
}
```
### Envía la elegida [Sección titulada «Envía la elegida»](#envía-la-elegida) * curl
```bash
curl -X POST "https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/select" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"optionId": "1042…"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/select', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"optionId": "1042…"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/select",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"optionId": "1042…"
},
)
data = res.json()["data"]
```
Devuelve la cuenta conectada (`201`). La sesión caduca a la hora. ## Redes disponibles [Sección titulada «Redes disponibles»](#redes-disponibles) `instagram`, `facebook`, `tiktok`, `youtube`, `linkedin`, `x`, `threads`, `bluesky`, `pinterest`, `reddit`, `google-business`, `discord` y `snapchat`. Telegram llegará pronto. ## Listar y vigilar cuentas [Sección titulada «Listar y vigilar cuentas»](#listar-y-vigilar-cuentas) * curl
```bash
curl "https://api.marsial.dev/v1/accounts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Cada cuenta tiene un `status`: `active`, `needs_reconnection` (el token caducó o el usuario quitó permisos) o `disconnected`. Para comprobar en el momento si pueden publicar, usa `GET /v1/accounts/health`. Si una cuenta pide reconexión, repite el flujo con la misma red y perfil.
# Importar desde un CSV
> Crea muchas publicaciones a la vez desde un archivo CSV: columnas, formatos y comprobación previa.
Una fila, una publicación. Hasta 50 filas por petición, y cada fila se comprueba por su cuenta. ## El archivo [Sección titulada «El archivo»](#el-archivo) La primera fila son los nombres de las columnas. Separa con comas y pon entre comillas los textos que llevan comas o saltos de línea. Desde el panel puedes descargar una plantilla con las cuentas de tu perfil. publicaciones.csv
```bash
content,accounts,schedule_time,timezone,media_urls,first_comment
"Abrimos el lunes, ¡te esperamos!",acc_ig|acc_li,2026-11-02 09:00,Europe/Madrid,https://cdn.acme.com/tienda.jpg,#valencia
Idea para la semana que viene,acc_li,,,,
```
## Columnas [Sección titulada «Columnas»](#columnas) | Columna | Qué lleva | | --------------------------------------------------------- | ---------------------------------------------------------------------------------- | | `content` | El texto. Obligatorio salvo que haya `media_urls`. | | `accounts` | Ids de cuentas separados por `\|`. | | `group` | O el nombre de un grupo de cuentas (se suma a `accounts`). | | `schedule_time` | `2026-11-02 09:00` con `timezone`, o una fecha ISO con zona. Vacío: se publica ya. | | `timezone` | Zona horaria IANA, por ejemplo `Europe/Madrid`. | | `queue` | `true` para el siguiente hueco de la cola. | | `draft` | `true` para guardarla como borrador. | | `media_urls` | URLs https separadas por `\|`. El tipo sale de la extensión. | | `first_comment` | Primer comentario en Instagram, Facebook, LinkedIn, Threads y YouTube. | | `instagram_format`, `facebook_format` | `feed`, `reel` o `story`. | | `youtube_title`, `youtube_visibility`, `youtube_playlist` | Título, `public`/`unlisted`/`private` e id de lista. | | `tiktok_privacy` | Obligatoria con cuentas de TikTok: `public`, `friends`, `followers` o `private`. | | `pinterest_title`, `pinterest_link`, `pinterest_board` | Título, enlace y tablero del Pin. | | `reddit_subreddit`, `reddit_title` | Subreddit (sin `r/`) y título. | | `google_cta_type`, `google_cta_url` | Botón de Google Business y su enlace. | ## Comprueba y luego importa [Sección titulada «Comprueba y luego importa»](#comprueba-y-luego-importa) Con `dryRun: true` se revisa cada fila sin publicar nada. Después envía el mismo CSV sin `dryRun`: las filas válidas se crean y las demás vuelven con su error. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/import" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"csv": "content,accounts\nHola,acc_ig",
"dryRun": true
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/import', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"csv": "content,accounts\nHola,acc_ig",
"dryRun": true
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/import",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"csv": "content,accounts\nHola,acc_ig",
"dryRun": True
},
)
data = res.json()["data"]
```
200 OK
```json
{
"data": {
"total": 2,
"valid": 1,
"invalid": 1,
"dryRun": true,
"unknownColumns": [],
"rows": [
{ "row": 1, "ok": true },
{ "row": 2, "ok": false, "error": "accounts: acc_old is not a connected account" }
]
}
}
```
Precaución TikTok exige el consentimiento del usuario para cada publicación: importar el archivo cuenta como ese consentimiento, con comentarios permitidos y sin dúos ni stitch.
# Bandeja
> Lee y responde comentarios, menciones, mensajes directos y reseñas de las cuentas de un perfil.
La bandeja reúne lo que la gente dice de las cuentas de un perfil. Los listados piden el `profileId`; las acciones, la `accountId` a la que pertenece cada elemento. Los ids de la bandeja (`thr_…`, `cmt_…`, `mtn_…`, `cnv_…`, `rev_…`) son opacos y solo valen en tu workspace: guárdalos y devuélvelos tal cual. ## Comentarios [Sección titulada «Comentarios»](#comentarios) Primero, las publicaciones recientes con comentarios, también las que se publicaron fuera de Marsial: * curl
```bash
curl "https://api.marsial.dev/v1/inbox/posts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/posts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/posts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Después, los comentarios de una de ellas, con sus respuestas anidadas. Cada comentario dice en `can` lo que su red permite: responder, borrar, ocultar o dar me gusta. * curl
```bash
curl "https://api.marsial.dev/v1/inbox/posts/thr_…/comments?accountId=acc_3k9x2m" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/posts/thr_…/comments?accountId=acc_3k9x2m', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/posts/thr_…/comments?accountId=acc_3k9x2m",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Para responder bajo un comentario, manda su id en `commentId`; sin él, comentas en la publicación: * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/posts/thr_…/comments" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"text": "¡Gracias, Luis!",
"commentId": "cmt_…"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/posts/thr_…/comments', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"text": "¡Gracias, Luis!",
"commentId": "cmt_…"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/posts/thr_…/comments",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"text": "¡Gracias, Luis!",
"commentId": "cmt_…"
},
)
data = res.json()["data"]
```
Para ocultarlo o darle me gusta, `PATCH` con `hidden` o `liked`; para borrarlo, `DELETE`. Si prefieres que te avisemos de cada comentario nuevo, suscríbete a `comment.received` en los [webhooks](/webhooks/). ## Menciones [Sección titulada «Menciones»](#menciones) Publicaciones y comentarios de otras personas que etiquetan a tus cuentas, de los últimos 7 días: * **Instagram**: cuando te etiquetan en un comentario (`kind: "comment"`) o en el texto de su publicación (`kind: "caption"`). Solo cuentas conectadas a través de Facebook. Instagram manda el texto un momento después: hasta entonces, `content` llega vacío. * **LinkedIn**: cuando mencionan a tu página en una publicación (`kind: "post"`), con su `url`. - curl
```bash
curl "https://api.marsial.dev/v1/inbox/mentions?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
- Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/mentions?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
- Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/mentions?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
200 OK
```json
{
"data": {
"items": [
{
"id": "mtn_…",
"accountId": "acc_3k9x2m",
"platform": "instagram",
"kind": "comment",
"content": "¡Mirad lo que me ha llegado de @acme!",
"author": { "username": "lucia" },
"publishedAt": "2026-10-25T09:12:00.000Z",
"canReply": true
}
],
"nextCursor": null
}
}
```
Las menciones de Instagram se pueden responder (`canReply: true`): bajo el comentario que te etiquetó o como comentario en la publicación que lo hizo. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/mentions/mtn_…/reply" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"text": "¡Gracias por compartirlo, Lucía!"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/mentions/mtn_…/reply', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"text": "¡Gracias por compartirlo, Lucía!"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/mentions/mtn_…/reply",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"text": "¡Gracias por compartirlo, Lucía!"
},
)
data = res.json()["data"]
```
Precaución Responder envía un comentario público en la red, en nombre de la cuenta. Haz tus pruebas con una cuenta tuya de pruebas, nunca con la de un cliente. ## Mensajes directos [Sección titulada «Mensajes directos»](#mensajes-directos) Instagram, Facebook, X, Bluesky y Telegram. En X solo se ven los mensajes no cifrados. * curl
```bash
curl "https://api.marsial.dev/v1/inbox/conversations?profileId=prf_8f2k4d&status=active" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations?profileId=prf_8f2k4d&status=active', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/conversations?profileId=prf_8f2k4d&status=active",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Los mensajes de una conversación, de los más nuevos a los más antiguos (sigue con `cursor` para traer los anteriores): * curl
```bash
curl "https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Responder devuelve `201` con el `id` del mensaje (o `null` si la red no da uno): * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "¡Hola! Sí, nos quedan en talla M."
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"text": "¡Hola! Sí, nos quedan en talla M."
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"text": "¡Hola! Sí, nos quedan en talla M."
},
)
data = res.json()["data"]
```
El id de la conversación ya lleva su cuenta, así que estas llamadas no necesitan `accountId`. Solo los ids `cnv_…` guardados antes del 27 de octubre de 2026 lo siguen pidiendo. Precaución Instagram y Facebook solo dejan responder durante las 24 horas siguientes al último mensaje de la persona. Pasado ese plazo, la API devuelve un error con el motivo. Marca una conversación como leída con `POST …/read` y archívala o recupérala con `PATCH` y `status` (`archived` o `active`). Para enterarte al momento de cada mensaje nuevo, suscríbete a `message.received` en los [webhooks](/webhooks/). ## Reseñas [Sección titulada «Reseñas»](#reseñas) Google Business (de 1 a 5 estrellas) y Facebook (recomienda o no). `hasReply=false` deja solo las que faltan por responder. * curl
```bash
curl "https://api.marsial.dev/v1/inbox/reviews?profileId=prf_8f2k4d&hasReply=false" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/reviews?profileId=prf_8f2k4d&hasReply=false', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/reviews?profileId=prf_8f2k4d&hasReply=false",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
- curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/reviews/rev_…/reply" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"text": "¡Gracias por venir, Marta!"
}'
```
- Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/reviews/rev_…/reply', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"text": "¡Gracias por venir, Marta!"
}),
});
const { data } = await res.json();
```
- Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/reviews/rev_…/reply",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"text": "¡Gracias por venir, Marta!"
},
)
data = res.json()["data"]
```
Para borrar tu respuesta, `DELETE` en la misma ruta con `accountId`. Las reseñas nuevas llegan por webhook con `review.received`.
# Imágenes y vídeos
> Sube imágenes y vídeos y úsalos en tus publicaciones.
Puedes usar cualquier URL pública en `media`. Si el archivo está en tu equipo o en un almacenamiento privado, súbelo a Marsial en dos pasos: ### 1. Pide una URL de subida [Sección titulada «1. Pide una URL de subida»](#1-pide-una-url-de-subida) * curl
```bash
curl -X POST "https://api.marsial.dev/v1/media/upload-url" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "chaqueta.mp4",
"contentType": "video/mp4",
"size": 48211234
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/media/upload-url', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"filename": "chaqueta.mp4",
"contentType": "video/mp4",
"size": 48211234
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/media/upload-url",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"filename": "chaqueta.mp4",
"contentType": "video/mp4",
"size": 48211234
},
)
data = res.json()["data"]
```
200 OK
```json
{
"data": {
"uploadUrl": "https://…",
"publicUrl": "https://cdn.acme.com/chaqueta.mp4",
"kind": "video",
"expiresIn": 900
}
}
```
### 2. Sube el archivo con PUT [Sección titulada «2. Sube el archivo con PUT»](#2-sube-el-archivo-con-put)
```bash
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--data-binary @chaqueta.mp4
```
Después usa `publicUrl` en el `media` del post. ## Formatos y tamaños [Sección titulada «Formatos y tamaños»](#formatos-y-tamaños) | Tipo | Formatos | Máximo | | ------ | --------------- | ------ | | Imagen | JPEG, PNG, WebP | 20 MB | | GIF | GIF | 20 MB | | Vídeo | MP4, MOV, WebM | 1 GB | ## En el post [Sección titulada «En el post»](#en-el-post) Cada elemento de `media` lleva `type` (`image`, `video`, `gif` o `document`), `url` y, opcionalmente, `altText` para accesibilidad. Hasta 35 por post. Cada red aplica sus propios límites (por ejemplo, 10 imágenes en un carrusel de Instagram, 4 en X).
# Opciones por red
> Las opciones de cada red social al publicar: formatos, títulos, primer comentario, hilos y más.
Van dentro de cada destino, con el nombre de la red como clave. Todas son opcionales salvo las de TikTok. Un destino con opciones
```json
{
"accountId": "acc_ig",
"instagram": { "format": "reel", "firstComment": "#otoño" }
}
```
## Instagram [Sección titulada «Instagram»](#instagram) Las imágenes van al feed y un vídeo solo se publica como Reel. Varias imágenes forman un carrusel. * `format`string `feed`, `reel` o `story`. Por defecto, las imágenes van al feed y un vídeo es un Reel. Valores: `feed` · `reel` · `story` * `shareToFeed`boolean Solo Reels: `false` lo deja fuera de la cuadrícula del perfil. * `collaborators`string\[] Hasta 3 usuarios de empresa o creador invitados como colaboradores. No en Stories. máx. 3 elementos * `firstComment`string Comentario que se publica justo después. No en Stories. máx. 2200 * `coverUrl`string (uri) Solo Reels: imagen de portada. ## Facebook [Sección titulada «Facebook»](#facebook) * `format`string `feed`, `reel` o `story`. Valores: `feed` · `reel` · `story` * `reelTitle`string Solo Reels: título aparte del texto. máx. 255 * `firstComment`string Comentario que se publica justo después. No en Stories. máx. 10.000 ## TikTok [Sección titulada «TikTok»](#tiktok) TikTok obliga a que el usuario elija la privacidad y las interacciones, y a que acepte publicar tras ver la vista previa (`consent: true`). Sin estas opciones la petición se rechaza. * `privacy`stringobligatorio Quién lo ve: `public`, `friends`, `followers` o `private`. Valores: `public` · `friends` · `followers` · `private` * `allowComments`booleanobligatorio Permitir comentarios. * `allowDuet`boolean Permitir dúos. Por defecto: `false` * `allowStitch`boolean Permitir stitch. Por defecto: `false` * `commercialContent`string `own_brand` si promociona tu negocio, `paid_partnership` si es patrocinado. No con privacidad `private`. Valores: `own_brand` · `paid_partnership` * `autoAddMusic`boolean Solo fotos: TikTok puede añadir música recomendada. * `consent`trueobligatorio Siempre `true`: el usuario vio la vista previa y aceptó publicar. ## YouTube [Sección titulada «YouTube»](#youtube) Los vídeos verticales de menos de 3 minutos se publican como Shorts. Las listas de reproducción de una cuenta están en `GET /v1/accounts/{id}/youtube-playlists`. * `title`string Título del vídeo (hasta 100 caracteres). máx. 100 * `visibility`string `public`, `unlisted` o `private`. Valores: `public` · `unlisted` · `private` * `madeForKids`boolean Marca COPPA. YouTube puede limitar los vídeos que no la indican. * `categoryId`string Id numérico de categoría de YouTube. * `playlistId`string Añadirlo a esta lista de reproducción. máx. 100 * `tags`string\[] Etiquetas (500 caracteres en total). máx. 50 elementos * `firstComment`string Comentario que se publica justo después. máx. 10.000 * `thumbnailUrl`string (uri) Miniatura personalizada. * `containsSyntheticMedia`boolean Contiene contenido realista generado o alterado con IA. * `notifySubscribers`boolean `false` lo sube sin avisar a los suscriptores. ## LinkedIn [Sección titulada «LinkedIn»](#linkedin) * `firstComment`string Comentario que se publica justo después. máx. 10.000 * `disableLinkPreview`boolean No mostrar la vista previa del enlace. * `documentTitle`string Título de los documentos (PDF). máx. 400 ## X [Sección titulada «X»](#x) El texto del post es el primer tuit; `thread` añade las respuestas del hilo (280 caracteres cada una). * `thread`string\[] Respuestas del hilo, en orden. El texto del post es el primer tuit. máx. 25 elementos * `replySettings`string Quién puede responder: `following`, `mentionedUsers`, `subscribers` o `verified`. Valores: `following` · `mentionedUsers` · `subscribers` · `verified` ## Threads [Sección titulada «Threads»](#threads) Hilos de hasta 500 caracteres por publicación. * `thread`string\[] Respuestas del hilo, en orden. máx. 25 elementos * `topicTag`string Tema de la publicación. máx. 50 * `firstComment`string Comentario que se publica justo después. máx. 10.000 ## Bluesky [Sección titulada «Bluesky»](#bluesky) Hilos de hasta 300 caracteres por publicación. * `thread`string\[] Respuestas del hilo, en orden. máx. 25 elementos ## Pinterest [Sección titulada «Pinterest»](#pinterest) Sin `boardId` se usa el tablero elegido al conectar la cuenta. Los tableros de una cuenta están en `GET /v1/accounts/{id}/pinterest-boards`. * `title`string Título del Pin. máx. 100 * `link`string (uri) A dónde lleva el Pin. * `boardId`string Tablero. Por defecto, el elegido al conectar. máx. 100 ## Google Business [Sección titulada «Google Business»](#google-business) * `callToAction`object Botón de la publicación. ## Telegram [Sección titulada «Telegram»](#telegram) * `parseMode`string Formato del texto: `html` o `markdown`. Valores: `html` · `markdown` * `disableLinkPreview`boolean No mostrar la vista previa del enlace. * `silent`boolean Enviar sin sonido. * `protectContent`boolean Impedir reenviarlo o guardarlo. ## Snapchat [Sección titulada «Snapchat»](#snapchat) * `format`string `story` (desaparece a las 24 h), `saved_story` (queda en el perfil) o `spotlight`. Valores: `story` · `saved_story` · `spotlight` ## Reddit [Sección titulada «Reddit»](#reddit) * `subreddit`string Subreddit sin `r/`. * `title`string Título del post. máx. 300 * `link`string (uri) Lo convierte en un post de enlace. * `flairId`string Flair del subreddit. máx. 100 * `nsfw`boolean Marcarlo como NSFW. * `spoiler`boolean Marcarlo como spoiler.
# Números, llamadas y SMS
> Compra números en 67 países, recibe y haz llamadas con grabación y transcripción, y envía SMS cuyas respuestas llegan a la bandeja.
Un **número de teléfono** pertenece a un perfil. Todos los números reciben y hacen llamadas; los SMS se activan en los números que pueden enviarlos. Comprar, configurar y dar de baja números lo hacen los propietarios y admins (y las claves API); llamar y enviar SMS, cualquier miembro. Todo se cobra de tu [saldo](/billing/): cada número al mes (de 3 € a 30 €, según el país y el tipo), las llamadas por minuto y los SMS por segmento. ## Elegir y comprar un número [Sección titulada «Elegir y comprar un número»](#elegir-y-comprar-un-número) Los países, sus tipos de número y el precio al mes (en céntimos): * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/countries" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/countries', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/countries",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
En los países que venden al momento (como EE. UU. o Reino Unido) puedes buscar un número concreto y comprarlo: * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
- curl
```bash
curl -X POST "https://api.marsial.dev/v1/phone-numbers" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profileId": "prf_8f2k4d",
"country": "GB",
"numberType": "mobile",
"phoneNumber": "+447700900123",
"sms": true
}'
```
- Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"profileId": "prf_8f2k4d",
"country": "GB",
"numberType": "mobile",
"phoneNumber": "+447700900123",
"sms": true
}),
});
const { data } = await res.json();
```
- Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/phone-numbers",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"profileId": "prf_8f2k4d",
"country": "GB",
"numberType": "mobile",
"phoneNumber": "+447700900123",
"sms": True
},
)
data = res.json()["data"]
```
Sin `phoneNumber`, te damos uno cualquiera del país (o del prefijo de `areaCode`). Hace falta saldo para al menos un mes del número; sin él, la respuesta es `402`. Envía `idempotencyKey` si puedes reintentar la petición: un reintento nunca compra un segundo número. ## Países con KYC (España y la mayoría de Europa) [Sección titulada «Países con KYC (España y la mayoría de Europa)»](#países-con-kyc-españa-y-la-mayoría-de-europa) Donde la ley obliga a identificar al titular, la compra responde `202` con `status: "kyc_required"`. Pide el formulario del país: * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/kyc?country=ES" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc?country=ES', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/kyc?country=ES",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Cada campo tiene un `kind`: * `text` y `date`: van en `values`, por `requirementId` (las fechas como `AAAA-MM-DD`). * `file`: súbelo antes (PDF, JPEG o PNG, hasta 4 MB, en base64) y usa el `documentId` que devuelve. Para un DNI, las dos caras en un solo archivo. * `address`: va en `address`. * `action`: una verificación de identidad que el titular hace después con un enlace. Envía su nombre legal en `endUserFirstName` y `endUserLastName`. - curl
```bash
curl -X POST "https://api.marsial.dev/v1/phone-numbers/kyc/documents" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "dni.pdf",
"contentType": "application/pdf",
"data": "JVBERi0xLjQK…"
}'
```
- Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc/documents', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"filename": "dni.pdf",
"contentType": "application/pdf",
"data": "JVBERi0xLjQK…"
}),
});
const { data } = await res.json();
```
- Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/phone-numbers/kyc/documents",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"filename": "dni.pdf",
"contentType": "application/pdf",
"data": "JVBERi0xLjQK…"
},
)
data = res.json()["data"]
```
* curl
```bash
curl -X POST "https://api.marsial.dev/v1/phone-numbers/kyc" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profileId": "prf_8f2k4d",
"country": "ES",
"values": {
"d7e8f9a0-…": "Acme SL"
},
"documents": [
{
"requirementId": "e8f9a0b1-…",
"documentId": "kdoc_…"
}
],
"address": {
"requirementId": "f9a0b1c2-…",
"countryCode": "ES",
"streetAddress": "Gran Vía 1",
"locality": "Madrid",
"postalCode": "28013"
},
"submissionId": "pedido-123"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"profileId": "prf_8f2k4d",
"country": "ES",
"values": {
"d7e8f9a0-…": "Acme SL"
},
"documents": [
{
"requirementId": "e8f9a0b1-…",
"documentId": "kdoc_…"
}
],
"address": {
"requirementId": "f9a0b1c2-…",
"countryCode": "ES",
"streetAddress": "Gran Vía 1",
"locality": "Madrid",
"postalCode": "28013"
},
"submissionId": "pedido-123"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/phone-numbers/kyc",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"profileId": "prf_8f2k4d",
"country": "ES",
"values": {
"d7e8f9a0-…": "Acme SL"
},
"documents": [
{
"requirementId": "e8f9a0b1-…",
"documentId": "kdoc_…"
}
],
"address": {
"requirementId": "f9a0b1c2-…",
"countryCode": "ES",
"streetAddress": "Gran Vía 1",
"locality": "Madrid",
"postalCode": "28013"
},
"submissionId": "pedido-123"
},
)
data = res.json()["data"]
```
El número queda `pending_regulatory` mientras la operadora revisa los datos (de 1 a 3 días laborables) y no se cobra hasta que está `active`. Si la operadora pide la verificación de identidad, el número tiene `regulatory.idVerificationUrl`: envíaselo al titular. Si rechaza los datos, el número queda `regulatory_declined` con el motivo en `regulatory.declineReason`. ## Llamadas entrantes [Sección titulada «Llamadas entrantes»](#llamadas-entrantes) Decide a dónde van las llamadas y qué pasa alrededor. Solo cambian los campos que envíes: * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/phone-numbers/num_…/calls" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"forwardTo": "tel:+34600111222",
"voicemailEnabled": true,
"voicemailGreeting": "Hola, has llamado a Acme. Deja tu mensaje.",
"recordingEnabled": true,
"transcriptionEnabled": true,
"businessHoursEnabled": true,
"businessHoursTimezone": "Europe/Madrid",
"businessHours": [
{
"day": 1,
"open": "09:00",
"close": "18:00"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/calls', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"forwardTo": "tel:+34600111222",
"voicemailEnabled": true,
"voicemailGreeting": "Hola, has llamado a Acme. Deja tu mensaje.",
"recordingEnabled": true,
"transcriptionEnabled": true,
"businessHoursEnabled": true,
"businessHoursTimezone": "Europe/Madrid",
"businessHours": [
{
"day": 1,
"open": "09:00",
"close": "18:00"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/phone-numbers/num_…/calls",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"forwardTo": "tel:+34600111222",
"voicemailEnabled": True,
"voicemailGreeting": "Hola, has llamado a Acme. Deja tu mensaje.",
"recordingEnabled": True,
"transcriptionEnabled": True,
"businessHoursEnabled": True,
"businessHoursTimezone": "Europe/Madrid",
"businessHours": [
{
"day": 1,
"open": "09:00",
"close": "18:00"
}
]
},
)
data = res.json()["data"]
```
`forwardTo` puede ser un teléfono (`tel:+E164`), una dirección SIP (`sip:…`) o un agente de voz con IA por WebSocket (`wss://…`). Sin desvío, o fuera de horario, la llamada va al buzón de voz. La grabación hace sonar antes un aviso; grabación y transcripción cuestan algo más por minuto. ## Llamar [Sección titulada «Llamar»](#llamar) Marsial llama a `to` desde tu número y, cuando contesta, le conecta con `forwardTo`: tu móvil, una dirección SIP o tu agente de voz. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/calls" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"numberId": "num_…",
"to": "+34611222333",
"forwardTo": "tel:+34600111222",
"record": true
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/calls', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"numberId": "num_…",
"to": "+34611222333",
"forwardTo": "tel:+34600111222",
"record": true
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/calls",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"numberId": "num_…",
"to": "+34611222333",
"forwardTo": "tel:+34600111222",
"record": True
},
)
data = res.json()["data"]
```
Antes puedes saber lo que costará: * curl
```bash
curl "https://api.marsial.dev/v1/calls/estimate?to=%2B34611222333&minutes=5&numberId=num_%E2%80%A6" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/calls/estimate?to=%2B34611222333&minutes=5&numberId=num_%E2%80%A6', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/calls/estimate?to=%2B34611222333&minutes=5&numberId=num_%E2%80%A6",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Con `numberId`, la respuesta dice además si ese número puede llegar al destino (`reachable`). Algunos números, como los de Canadá, solo llaman y envían SMS dentro de su país: entonces `reachable` es `false` y `note` explica por qué. El historial de un número, con la duración, el coste y un fragmento de la transcripción: * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/num_…/calls" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/calls', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/num_…/calls",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
`GET /v1/calls/{id}` trae la transcripción completa y `GET /v1/calls/{id}/recording` un enlace a la grabación que dura 15 minutos. ## SMS [Sección titulada «SMS»](#sms) Activa los SMS en un número que pueda enviarlos: * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/phone-numbers/num_…/sms" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/sms', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"enabled": true
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/phone-numbers/num_…/sms",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"enabled": True
},
)
data = res.json()["data"]
```
- curl
```bash
curl -X POST "https://api.marsial.dev/v1/sms/messages" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"numberId": "num_…",
"to": "+447700900123",
"text": "Tu pedido 4821 ya está en camino"
}'
```
- Node
```js
const res = await fetch('https://api.marsial.dev/v1/sms/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"numberId": "num_…",
"to": "+447700900123",
"text": "Tu pedido 4821 ya está en camino"
}),
});
const { data } = await res.json();
```
- Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/sms/messages",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"numberId": "num_…",
"to": "+447700900123",
"text": "Tu pedido 4821 ya está en camino"
},
)
data = res.json()["data"]
```
Las respuestas llegan a la [bandeja](/guides/inbox/) como conversaciones de la plataforma `sms`, y a tu webhook como `message.received`. Quien responde STOP no puede volver a recibir SMS de ese número (`GET /v1/phone-numbers/{id}/sms/opt-outs`). Precaución Los SMS funcionan con números de Reino Unido, Irlanda, Países Bajos, Bélgica, Finlandia, Suecia, Polonia, Lituania, Canadá, México, Brasil, Australia y Sudáfrica. Los números de España aún no admiten SMS, y los de EE. UU. necesitan un registro de operadora (10DLC) que todavía no ofrecemos. ## En el panel y para agentes [Sección titulada «En el panel y para agentes»](#en-el-panel-y-para-agentes) En el panel, la sección **Teléfono** tiene los números (comprar, el formulario del titular, los ajustes de llamadas, los SMS, dar de baja) y el historial de llamadas con grabaciones y transcripciones. Los agentes de IA pueden listar números, enviar SMS, llamar y leer el historial por el [servidor MCP](/ai/); comprar números queda para las personas. Aún no ofrecemos traer tu número de otra operadora (portabilidad), remitentes con el nombre de tu marca ni llamar desde el navegador.
# Publicar
> Publica ahora, programa, usa la cola o guarda borradores en una o varias redes.
Una petición, todas las redes. Cada destino puede llevar su propio texto, medios y opciones. ## Ahora [Sección titulada «Ahora»](#ahora) * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Lanzamos la colección de otoño 🍂",
"targets": [
{
"accountId": "acc_ig"
},
{
"accountId": "acc_li"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Lanzamos la colección de otoño 🍂",
"targets": [
{
"accountId": "acc_ig"
},
{
"accountId": "acc_li"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Lanzamos la colección de otoño 🍂",
"targets": [
{
"accountId": "acc_ig"
},
{
"accountId": "acc_li"
}
]
},
)
data = res.json()["data"]
```
## Programado [Sección titulada «Programado»](#programado) Añade `scheduledFor` en ISO 8601 con zona horaria. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Abrimos el viernes a las 9",
"scheduledFor": "2026-10-30T09:00:00+01:00",
"targets": [
{
"accountId": "acc_ig"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Abrimos el viernes a las 9",
"scheduledFor": "2026-10-30T09:00:00+01:00",
"targets": [
{
"accountId": "acc_ig"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Abrimos el viernes a las 9",
"scheduledFor": "2026-10-30T09:00:00+01:00",
"targets": [
{
"accountId": "acc_ig"
}
]
},
)
data = res.json()["data"]
```
Puedes cancelarla antes de que salga con `POST /v1/posts/{id}/cancel`. ## En la cola [Sección titulada «En la cola»](#en-la-cola) Con `queue: true` toma el siguiente hueco libre de la [cola](/guides/queue/) del perfil. Todas las cuentas tienen que ser del mismo perfil. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Consejo del día",
"queue": true,
"targets": [
{
"accountId": "acc_ig"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Consejo del día",
"queue": true,
"targets": [
{
"accountId": "acc_ig"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Consejo del día",
"queue": True,
"targets": [
{
"accountId": "acc_ig"
}
]
},
)
data = res.json()["data"]
```
## Borrador [Sección titulada «Borrador»](#borrador) Con `draft: true` se guarda sin publicar ni programar. ## Texto y medios por red [Sección titulada «Texto y medios por red»](#texto-y-medios-por-red) Cada destino puede sustituir el texto (`content`) y los medios (`media`) del post, y llevar las opciones de su red con la clave de la red (`instagram`, `youtube`, `tiktok`…). Mira [Opciones por red](/guides/network-options/). * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Así se hace nuestra chaqueta",
"media": [
{
"type": "video",
"url": "https://cdn.acme.com/chaqueta.mp4"
}
],
"targets": [
{
"accountId": "acc_ig",
"instagram": {
"format": "reel",
"firstComment": "#otoño #moda"
}
},
{
"accountId": "acc_yt",
"youtube": {
"title": "Así se hace nuestra chaqueta",
"visibility": "public"
}
},
{
"accountId": "acc_x",
"content": "Así se hace nuestra chaqueta 🧵",
"x": {
"thread": [
"1/ Empieza en el taller…"
]
}
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Así se hace nuestra chaqueta",
"media": [
{
"type": "video",
"url": "https://cdn.acme.com/chaqueta.mp4"
}
],
"targets": [
{
"accountId": "acc_ig",
"instagram": {
"format": "reel",
"firstComment": "#otoño #moda"
}
},
{
"accountId": "acc_yt",
"youtube": {
"title": "Así se hace nuestra chaqueta",
"visibility": "public"
}
},
{
"accountId": "acc_x",
"content": "Así se hace nuestra chaqueta 🧵",
"x": {
"thread": [
"1/ Empieza en el taller…"
]
}
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Así se hace nuestra chaqueta",
"media": [
{
"type": "video",
"url": "https://cdn.acme.com/chaqueta.mp4"
}
],
"targets": [
{
"accountId": "acc_ig",
"instagram": {
"format": "reel",
"firstComment": "#otoño #moda"
}
},
{
"accountId": "acc_yt",
"youtube": {
"title": "Así se hace nuestra chaqueta",
"visibility": "public"
}
},
{
"accountId": "acc_x",
"content": "Así se hace nuestra chaqueta 🧵",
"x": {
"thread": [
"1/ Empieza en el taller…"
]
}
}
]
},
)
data = res.json()["data"]
```
## Estados [Sección titulada «Estados»](#estados) | Estado | Qué significa | | ------------------ | ------------------------------------------------------------------------------------------------ | | `draft` | Borrador, sin fecha. | | `pending_approval` | Esperando a que un propietario o admin la apruebe. No sale hasta entonces. | | `scheduled` | Programada o en la cola, esperando su hora. | | `paused` | Estaba programada cuando terminó la prueba gratis sin recarga. No sale hasta la primera recarga. | | `publishing` | Se está enviando a las redes. | | `published` | Publicada en todas. Cada destino tiene su `url`. | | `partial` | Publicada en algunas y fallida en otras. Reintenta las fallidas con `POST /v1/posts/{id}/retry`. | | `failed` | No salió en ninguna. Cada destino explica el motivo en `error`. | | `cancelled` | Cancelada antes de salir. | | `removed` | Salió y después se retiró de todas las redes. | | `deleted` | Borrada de Marsial. Solo aparece en el evento `post.deleted`. | ## Editar [Sección titulada «Editar»](#editar) Mientras no ha salido (borrador, programada, con error o cancelada) puedes cambiar cualquier cosa con `PATCH /v1/posts/{id}`. Lo que no envíes se mantiene; `targets` sustituye la lista entera. * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Abrimos el viernes a las 10",
"scheduledFor": "2026-10-30T10:00:00+01:00"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Abrimos el viernes a las 10",
"scheduledFor": "2026-10-30T10:00:00+01:00"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Abrimos el viernes a las 10",
"scheduledFor": "2026-10-30T10:00:00+01:00"
},
)
data = res.json()["data"]
```
Con `draft: false` un borrador se publica: ahora, en `scheduledFor` o en la cola. Una vez publicada, solo se puede cambiar el texto, y solo en las redes que lo permiten: X (cuentas Premium, durante la primera hora), Facebook, LinkedIn, YouTube, Pinterest, Google Business, Telegram, Discord y Reddit. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/edit" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Texto corregido"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/edit', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Texto corregido"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/edit",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Texto corregido"
},
)
data = res.json()["data"]
```
## Aprobación [Sección titulada «Aprobación»](#aprobación) Con `requiresApproval: true` la publicación queda en `pending_approval`: no sale hasta que alguien la apruebe. Si el espacio de trabajo exige aprobación (`PATCH /v1/workspace` con `requireApproval: true`, o desde Ajustes → Equipo en el panel), las de los miembros pasan siempre por aquí. Las de propietarios, admins y claves API no, salvo que lo pidan. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Nueva colección",
"scheduledFor": "2026-11-06T09:00:00+01:00",
"requiresApproval": true,
"targets": [
{
"accountId": "acc_ig"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Nueva colección",
"scheduledFor": "2026-11-06T09:00:00+01:00",
"requiresApproval": true,
"targets": [
{
"accountId": "acc_ig"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Nueva colección",
"scheduledFor": "2026-11-06T09:00:00+01:00",
"requiresApproval": True,
"targets": [
{
"accountId": "acc_ig"
}
]
},
)
data = res.json()["data"]
```
Un propietario, un admin o una clave API decide con `POST /v1/posts/{id}/review`. Al aprobarla se programa para su fecha, entra en la cola si la pidió o sale ya si su fecha pasó mientras esperaba. Al rechazarla vuelve a borrador con la nota, y tu webhook recibe `post.rejected`. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/review" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "reject",
"note": "Cambia la foto de portada"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"decision": "reject",
"note": "Cambia la foto de portada"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/review",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"decision": "reject",
"note": "Cambia la foto de portada"
},
)
data = res.json()["data"]
```
Editarla mientras espera no la publica: sigue pendiente. Quien la escribió puede retirarla con `POST /v1/posts/{id}/cancel`. ## Reciclar [Sección titulada «Reciclar»](#reciclar) Una publicación que funciona puede volver a salir sola: cada N semanas o meses, como una publicación nueva. Para cuando llega a `maxCopies` o pasa `until`, y las `variations` se usan por turnos para que no salga siempre el mismo texto. * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"every": 2,
"unit": "month",
"maxCopies": 6,
"variations": [
"Vuelve el clásico de otoño 🍂",
"Por si te lo perdiste: nuestro clásico de otoño"
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"every": 2,
"unit": "month",
"maxCopies": 6,
"variations": [
"Vuelve el clásico de otoño 🍂",
"Por si te lo perdiste: nuestro clásico de otoño"
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"every": 2,
"unit": "month",
"maxCopies": 6,
"variations": [
"Vuelve el clásico de otoño 🍂",
"Por si te lo perdiste: nuestro clásico de otoño"
]
},
)
data = res.json()["data"]
```
- Cada copia es una publicación propia con `recycledFrom`, y tu webhook recibe `post.recycled`. - YouTube y TikTok no permiten repetir contenido: esas cuentas se quedan fuera de las copias. - Cada cuenta puede tener hasta 10 publicaciones reciclándose a la vez. - `DELETE /v1/posts/{id}/recycling` lo para; las copias ya creadas se quedan. ## Métricas [Sección titulada «Métricas»](#métricas) `GET /v1/posts/{id}/metrics` devuelve impresiones, alcance, reproducciones, me gusta, comentarios, compartidos, guardados y clics, en total y por cuenta. Llegan unos minutos después de publicar; hasta entonces devuelve `null`. Cada red da solo las suyas: las demás valen `0`. ## Grupos de cuentas [Sección titulada «Grupos de cuentas»](#grupos-de-cuentas) Guarda selecciones de cuentas (por ejemplo, “Todas las de Acme”) con `POST /v1/account-groups` y úsalas al importar un CSV o desde el panel. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/account-groups" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Todas las de Acme",
"accountIds": [
"acc_ig",
"acc_li",
"acc_x"
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/account-groups', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Todas las de Acme",
"accountIds": [
"acc_ig",
"acc_li",
"acc_x"
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/account-groups",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"name": "Todas las de Acme",
"accountIds": [
"acc_ig",
"acc_li",
"acc_x"
]
},
)
data = res.json()["data"]
```
## Retirar y borrar [Sección titulada «Retirar y borrar»](#retirar-y-borrar) * `POST /v1/posts/{id}/unpublish` la retira de todas las redes, o solo de `accountId`. Instagram y TikTok no lo permiten por API: hay que borrarla en la app. * `DELETE /v1/posts/{id}` la borra de Marsial y, si sigue publicada, la retira antes de cada red (no hace falta `unpublish`). Instagram y TikTok no se pueden retirar por API: bórrala en la app y después aquí con `?keepLive=true`.
# Cola de publicación
> Huecos semanales por perfil para publicar sin calcular fechas.
La cola son huecos que se repiten cada semana. Un post con `queue: true` toma el siguiente libre, así puedes ir llenando el calendario sin calcular fechas. * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 3,
"time": "13:30"
},
{
"dayOfWeek": 5,
"time": "18:00"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 3,
"time": "13:30"
},
{
"dayOfWeek": 5,
"time": "18:00"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 3,
"time": "13:30"
},
{
"dayOfWeek": 5,
"time": "18:00"
}
]
},
)
data = res.json()["data"]
```
- `dayOfWeek` va de `0` (domingo) a `6` (sábado). - `time` es `HH:mm` en 24 horas, en la zona horaria de la cola. - `PUT` sustituye todos los huecos. `DELETE` borra la cola. - La respuesta incluye `nextSlots`: los próximos huecos libres.
# Reciclar publicaciones
> Vuelve a publicar automáticamente una publicación cada cierto tiempo, con variaciones de texto.
Reciclar una publicación es pedir a Marsial que la vuelva a sacar cada cierto tiempo: un evergreen de tu blog cada mes, una oferta cada semana. Cada vez se crea una **copia**, una publicación nueva con su propio id y `recycledFrom` apuntando a la original. ## Activarlo [Sección titulada «Activarlo»](#activarlo) * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"every": 2,
"unit": "week",
"maxCopies": 6,
"timezone": "Europe/Madrid",
"variations": [
"Vuelve nuestra chaqueta de otoño 🍂",
"La chaqueta que más pedís, otra vez disponible"
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"every": 2,
"unit": "week",
"maxCopies": 6,
"timezone": "Europe/Madrid",
"variations": [
"Vuelve nuestra chaqueta de otoño 🍂",
"La chaqueta que más pedís, otra vez disponible"
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"every": 2,
"unit": "week",
"maxCopies": 6,
"timezone": "Europe/Madrid",
"variations": [
"Vuelve nuestra chaqueta de otoño 🍂",
"La chaqueta que más pedís, otra vez disponible"
]
},
)
data = res.json()["data"]
```
| Campo | Qué hace | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `every` y `unit` | Cada cuántas semanas (`week`) o meses (`month`). De 1 a 52. | | `startAt` | Cuándo sale la primera copia. Por defecto, un intervalo después de la fecha de la publicación. | | `maxCopies` | Parar después de tantas copias (hasta 100). | | `until` | Parar después de esta fecha. | | `variations` | Entre 2 y 20 textos que se usan por turnos en vez del original. El texto propio de un destino sigue mandando. | | `timezone` | La zona horaria en la que se cuenta el intervalo, para que las copias mantengan su hora local cuando cambia la hora. UTC por defecto. | ## Seguirlo y pararlo [Sección titulada «Seguirlo y pararlo»](#seguirlo-y-pararlo) La publicación original lleva `recycling` con la regla, si está activa, cuántas copias lleva y cuándo sale la siguiente (`nextAt`). Cada copia dispara el webhook `post.recycled` al crearse y después los de cualquier publicación (`post.published`, `post.failed`…). * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
Solo se reciclan publicaciones originales con fecha y en redes que aceptan repetir contenido. Las copias no se pueden reciclar a su vez.
# Equipo y roles
> Quién puede hacer qué en un espacio de trabajo, y cómo se invita a más gente.
Un espacio de trabajo puede tener varias personas, cada una con un rol: | Rol | Puede | | --------------- | -------------------------------------------------------------------------------------------------------------------------------- | | **Propietario** | Todo, también el saldo y la facturación. Hay uno por espacio de trabajo. | | **Admin** | Gestionar el equipo, las claves API y los webhooks, y aprobar publicaciones. | | **Miembro** | Publicar, responder y ver las analíticas. Si la [aprobación](/guides/approval/) está activa, sus publicaciones esperan revisión. | Las **claves API** no tienen rol: quien tiene una controla el espacio de trabajo entero. Guárdalas en tu servidor y nunca en una app o una web. ## Ver el equipo [Sección titulada «Ver el equipo»](#ver-el-equipo) * curl
```bash
curl "https://api.marsial.dev/v1/team" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/team', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/team",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Invitar y cambiar roles [Sección titulada «Invitar y cambiar roles»](#invitar-y-cambiar-roles) Las invitaciones, los cambios de rol y las bajas se hacen desde el panel (Ajustes → Equipo): son operaciones de personas, no de integraciones, y la API las acepta solo con la sesión del panel. Cada invitación es un enlace que dura 7 días y que solo sirve para entrar con el email invitado.
# WhatsApp
> Plantillas, conversaciones que empiezas tú y difusiones desde tu número de WhatsApp Business.
Un número de WhatsApp Business se conecta a un perfil como cualquier cuenta (`acc_…`), con el alta integrada de Meta: `GET /v1/connect/whatsapp`. Si la cuenta de WhatsApp Business tiene varios números, Marsial vuelve con `select=` para que elijas uno, como con Facebook. Un número ya usado en la app de WhatsApp Business puede seguir en ella a la vez. WhatsApp **no recibe publicaciones**: se usa para conversar. ## Las dos reglas de WhatsApp [Sección titulada «Las dos reglas de WhatsApp»](#las-dos-reglas-de-whatsapp) * **La ventana de 24 horas.** Durante las 24 horas siguientes al último mensaje de una persona le respondes con lo que quieras, desde la [bandeja](/guides/inbox/). Fuera de esa ventana, o para escribir tú primero, solo vale una **plantilla aprobada**. * **El límite diario.** Un número nuevo puede escribir a 250 personas distintas al día; Meta lo amplía a medida que lo usas sin quejas. ## Plantillas [Sección titulada «Plantillas»](#plantillas) Meta revisa cada plantilla antes de que puedas usarla (suele tardar minutos, como mucho 24 horas). Los datos de cada persona van en `{{1}}`, `{{2}}`… con un ejemplo de cada uno. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "pedido_listo",
"category": "UTILITY",
"language": "es",
"components": [
{
"type": "BODY",
"text": "Hola {{1}}, tu pedido {{2}} ya está listo.",
"example": {
"body_text": [
[
"Lucía",
"#4821"
]
]
}
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "pedido_listo",
"category": "UTILITY",
"language": "es",
"components": [
{
"type": "BODY",
"text": "Hola {{1}}, tu pedido {{2}} ya está listo.",
"example": {
"body_text": [
[
"Lucía",
"#4821"
]
]
}
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"name": "pedido_listo",
"category": "UTILITY",
"language": "es",
"components": [
{
"type": "BODY",
"text": "Hola {{1}}, tu pedido {{2}} ya está listo.",
"example": {
"body_text": [
[
"Lucía",
"#4821"
]
]
}
}
]
},
)
data = res.json()["data"]
```
Empieza como `PENDING`; con `GET /v1/accounts/{id}/whatsapp/templates` ves cuándo pasa a `APPROVED` (o `REJECTED`). La categoría decide lo que cobra Meta: `UTILITY` (pedidos, citas), `MARKETING` o `AUTHENTICATION` (códigos). ## Escribir primero [Sección titulada «Escribir primero»](#escribir-primero) Con una plantilla aprobada abres la conversación. La respuesta llega a la bandeja y como `message.received`, y desde ahí sigues con `POST /v1/inbox/conversations/{id}/messages`. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/conversations" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"phone": "+34 611 222 333",
"template": {
"name": "pedido_listo",
"language": "es",
"params": [
"Lucía",
"#4821"
]
}
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"phone": "+34 611 222 333",
"template": {
"name": "pedido_listo",
"language": "es",
"params": [
"Lucía",
"#4821"
]
}
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/conversations",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"phone": "+34 611 222 333",
"template": {
"name": "pedido_listo",
"language": "es",
"params": [
"Lucía",
"#4821"
]
}
},
)
data = res.json()["data"]
```
## Difusiones [Sección titulada «Difusiones»](#difusiones) Una plantilla aprobada a muchos números, ahora o programada. Cada `{{n}}` se rellena por persona con su nombre o su teléfono, o con un texto igual para todos. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Black Friday",
"template": {
"name": "oferta_black_friday",
"language": "es",
"variables": [
{
"field": "name"
},
{
"value": "BF30"
}
]
},
"phones": [
"+34611222333",
"+34622333444"
],
"scheduledFor": "2026-11-27T09:00:00+01:00"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Black Friday",
"template": {
"name": "oferta_black_friday",
"language": "es",
"variables": [
{
"field": "name"
},
{
"value": "BF30"
}
]
},
"phones": [
"+34611222333",
"+34622333444"
],
"scheduledFor": "2026-11-27T09:00:00+01:00"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"name": "Black Friday",
"template": {
"name": "oferta_black_friday",
"language": "es",
"variables": [
{
"field": "name"
},
{
"value": "BF30"
}
]
},
"phones": [
"+34611222333",
"+34622333444"
],
"scheduledFor": "2026-11-27T09:00:00+01:00"
},
)
data = res.json()["data"]
```
`GET /v1/accounts/{id}/whatsapp/broadcasts` devuelve cada difusión con cuántos la recibieron, la leyeron o fallaron; `POST …/broadcasts/{broadcastId}/cancel` para la que está programada o lo que queda por enviar. Solo a quien quiere recibirlos Escribe solo a personas que han aceptado recibir tus mensajes. Las quejas bajan la calidad del número y Meta puede limitarlo. ## Lo que cuesta [Sección titulada «Lo que cuesta»](#lo-que-cuesta) Cada mensaje que envías (cada destinatario de una difusión) cuenta como un [mensaje enviado](/billing/). Además, Meta cobra su tarifa por cada plantilla directamente a tu cuenta de WhatsApp Business. Responder dentro de la ventana de 24 horas no tiene tarifa de Meta. En el panel, todo esto está en **Bandeja → WhatsApp**.
# Introducción
> Qué es Marsial, cómo se organiza y qué redes cubre.
Marsial es una API y un panel para publicar en redes sociales. Conectas las cuentas de una marca (o las de tus clientes) una vez y desde ahí publicas, programas, respondes comentarios y mensajes y mides resultados en todas ellas con el mismo formato. ## Cómo se organiza [Sección titulada «Cómo se organiza»](#cómo-se-organiza) Todo cuelga de tres objetos, los mismos en la API y en el panel: 1. **Perfil** (`prf_…`): una marca o un cliente. Agrupa sus cuentas, su cola y su zona horaria. 2. **Cuenta** (`acc_…`): una cuenta social conectada a un perfil, por ejemplo el Instagram de Acme. 3. **Publicación** (`pst_…`): un texto con imágenes o vídeos que sale en una o varias cuentas, cada una con sus opciones. Lo que haces en el panel se ve en la API y al revés: si tu equipo programa una publicación desde el panel, tu integración la recibe por webhook igual que las suyas. Los detalles están en [Conceptos](/concepts/). ## La API en una línea [Sección titulada «La API en una línea»](#la-api-en-una-línea) * **Base URL**: `https://api.marsial.dev/v1` * **Autenticación**: `Authorization: Bearer ` ([cómo conseguirla](/authentication/)). * **Formato**: JSON. Las respuestas van en `data`; los errores, en `error` con un `code` estable ([errores](/errors/)). * **Fechas**: ISO 8601 con zona horaria, por ejemplo `2026-10-30T09:00:00+01:00`. * **Documento OpenAPI**: [`/openapi.json`](https://api.marsial.dev/openapi.json), para generar clientes o importarlo en Postman. ## Redes [Sección titulada «Redes»](#redes) | Red | Qué publica | Comentarios | Menciones | Mensajes directos | Reseñas | | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------- | ------------------------- | ----------------- | ------- | | Instagram | Feed, reels, historias y carruseles | Sí | Sí, y se pueden responder | Sí | — | | Facebook | Páginas: feed, reels e historias | Sí | — | Sí | Sí | | TikTok | Vídeos | Sí | — | — | — | | YouTube | Vídeos y Shorts | Sí | — | — | — | | LinkedIn | Perfiles y páginas | Sí | Sí (páginas) | — | — | | X | Posts e hilos | Sí | — | Sí (no cifrados) | — | | Threads | Posts e hilos | Sí | — | — | — | | Bluesky | Posts e hilos | Sí | — | Sí | — | | Pinterest | Pines | — | — | — | — | | Reddit | Publicaciones en subreddits | — | — | — | — | | Snapchat | Historias y Spotlight del perfil público | — | — | — | — | | Telegram (pronto) | Mensajes en canales y grupos | — | — | Sí | — | | Discord | Mensajes en canales | — | — | — | — | | Slack | Mensajes en canales | — | — | Sí | — | | WhatsApp | Plantillas y difusiones (no publica) | — | — | Sí | — | | Google Business | Publicaciones de la ficha | — | — | — | Sí | | WordPress | Artículos del blog (WordPress.com y autoalojado) | — | — | — | — | | Shopify | Artículos del blog de la tienda | — | — | — | — | | Wix | Artículos del blog | — | — | — | — | | Webflow | Elementos de colecciones del CMS | — | — | — | — | | **HubSpot** no publica: conectado a un perfil, convierte a quien escribe a su bandeja en contactos de HubSpot y guarda cada mensaje en su ficha. Se configura con `PATCH /v1/accounts/{id}/crm-settings` (`syncContacts`, `logMessages`). | | | | | | **Anuncios**: Meta, Google, LinkedIn, TikTok, Pinterest, X y Reddit Ads se conectan como cuentas de anuncios (`meta-ads`…) para ver campañas, pausarlas, cambiar presupuestos y promocionar publicaciones. Ver [Anuncios](/guides/ads/). Las [analíticas](/guides/analytics/) (seguidores, interacciones, mejores horas) se leen por perfil o por cuenta. [Inicio rápido](/quickstart/)De cero a tu primera publicación en 5 minutos.
# Inicio rápido
> Publica tu primer post con la API de Marsial en 5 minutos.
Cuatro peticiones: perfil, conexión, cuenta y publicación. ## 1. Consigue tu clave API [Sección titulada «1. Consigue tu clave API»](#1-consigue-tu-clave-api) Entra en el [panel](https://app.marsial.dev), ve a **Desarrolladores → Claves API** y crea una. Se muestra una sola vez: guárdala como variable de entorno.
```bash
export MARSIAL_API_KEY="marsial_live_…"
```
## 2. Crea un perfil [Sección titulada «2. Crea un perfil»](#2-crea-un-perfil) Un perfil agrupa las cuentas de una marca o de uno de tus clientes. Guarda su `id`. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/profiles" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme",
"timezone": "Europe/Madrid"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/profiles', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Acme",
"timezone": "Europe/Madrid"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/profiles",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"name": "Acme",
"timezone": "Europe/Madrid"
},
)
data = res.json()["data"]
```
201 Created
```json
{
"data": {
"id": "prf_8f2k4d",
"name": "Acme",
"timezone": "Europe/Madrid",
"createdAt": "2026-10-23T10:00:00.000Z",
"updatedAt": "2026-10-23T10:00:00.000Z"
}
}
```
## 3. Conecta una cuenta [Sección titulada «3. Conecta una cuenta»](#3-conecta-una-cuenta) Pide la URL de conexión de la red y abre esa URL en el navegador del usuario. Cuando autorice, volverá a tu `redirectUrl`. * curl
```bash
curl "https://api.marsial.dev/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
Vuelta a tu app
```http
https://app.acme.com/conectado?connected=instagram&accountId=acc_3k9x2m&username=acme
```
## 4. Publica [Sección titulada «4. Publica»](#4-publica) Manda el texto y las cuentas. Sin `scheduledFor` se publica ahora mismo. * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "¡Hola desde Marsial! 👋",
"targets": [
{
"accountId": "acc_3k9x2m"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "¡Hola desde Marsial! 👋",
"targets": [
{
"accountId": "acc_3k9x2m"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "¡Hola desde Marsial! 👋",
"targets": [
{
"accountId": "acc_3k9x2m"
}
]
},
)
data = res.json()["data"]
```
201 Created
```json
{
"data": {
"id": "pst_7q1w0e",
"status": "publishing",
"targets": [
{ "accountId": "acc_3k9x2m", "platform": "instagram", "status": "pending" }
]
}
}
```
Unos segundos después la publicación pasa a `published` y cada destino lleva su `url`. Consúltalo con `GET /v1/posts/{id}` o, mejor, con un [webhook](/webhooks/).
# Referencia de la API
> Cada endpoint de la API de Marsial, generado del documento OpenAPI. Base URL:
Cada endpoint de la API de Marsial, generado del documento OpenAPI. Base URL: `https://api.marsial.dev/v1` · [Documento OpenAPI (JSON)](https://api.marsial.dev/openapi.json) [Publicaciones](/reference/posts/)Publica ahora, programa, usa la cola o guarda borradores en una o varias cuentas. (14 endpoints) [Multimedia](/reference/media/)Sube imágenes y vídeos a Marsial antes de publicarlos. (1 endpoint) [Perfiles](/reference/profiles/)Un perfil es una marca o un cliente final. Las cuentas sociales se conectan a un perfil. (5 endpoints) [Conexión](/reference/connect/)Conecta una cuenta social o un sitio: manda al usuario a la URL y Marsial lo devuelve a tu redirectUrl. (4 endpoints) [Cuentas](/reference/accounts/)Cuentas sociales conectadas, si pueden publicar, y sus tableros, listas y subreddits. (8 endpoints) [Grupos de cuentas](/reference/account-groups/)Selecciones de cuentas guardadas, para publicar en todas a la vez. (4 endpoints) [Blogs](/reference/blogs/)Artículos en sitios de WordPress, Shopify, Wix y Webflow: listar, crear borradores, programar, publicar, cambiar y borrar. Estas cuentas reciben artículos, no publicaciones. (6 endpoints) [Cola](/reference/queue/)Huecos semanales por perfil. Los posts con \`queue: true\` toman el siguiente libre. (3 endpoints) [Bandeja](/reference/inbox/)Mensajes directos, comentarios y reseñas de las cuentas de un perfil. Los listados piden el perfil; las acciones, la cuenta a la que pertenece cada elemento. (15 endpoints) [WhatsApp](/reference/whatsapp/)Números de WhatsApp Business: plantillas que revisa Meta, escribir primero con una plantilla aprobada (POST /inbox/conversations) y difusiones a muchos números. Las respuestas dentro de las 24 horas van por la bandeja. Estas cuentas no publican. (7 endpoints) [Anuncios](/reference/ads/)Campañas en Meta, Google, LinkedIn, TikTok, Pinterest, X y Reddit con una conexión de anuncios (plataforma \`meta-ads\`, \`google-ads\`…): listarlas con gasto y resultados, pausar, reanudar, cambiar presupuestos, promocionar publicaciones, crear campañas y enviar conversiones. Los presupuestos van en unidades enteras de la moneda, nunca en céntimos. (9 endpoints) [Números de teléfono](/reference/phone-numbers/)Números para llamadas y SMS: países y precios, comprar uno (los países que regulan los números piden antes la identidad del titular: KYC), decidir a dónde van las llamadas y activar los SMS. Los gestionan propietarios y admins; cada número se cobra al mes del saldo. (11 endpoints) [Llamadas](/reference/calls/)Llama desde tus números (Marsial llama a la persona y la conecta con tu teléfono, una dirección SIP o un agente de voz con IA), lee el historial con grabaciones y transcripciones y calcula lo que cuesta una llamada. (7 endpoints) [SMS](/reference/sms/)Envía SMS y MMS desde tus números. Las respuestas llegan a la bandeja (plataforma \`sms\`) y como eventos \`message.received\`. (2 endpoints) [Automatizaciones](/reference/automations/)Comentario a mensaje: a quien comente una palabra clave, se le responde con un mensaje privado (Instagram, Facebook) o en público (todas las redes). (6 endpoints) [Analíticas](/reference/analytics/)Seguidores, totales diarios, mejores horas para publicar y mejores publicaciones, por perfil o por cuenta. (4 endpoints) [Webhooks](/reference/webhooks/)Recibe los eventos de Marsial en tu endpoint HTTPS. (4 endpoints) [Workspace](/reference/workspace/)Tu workspace y quién está llamando. (3 endpoints) [Equipo](/reference/team/)Miembros e invitaciones. Propietarios y admins gestionan el equipo; los miembros publican y responden. (6 endpoints) [Facturación](/reference/billing/)Una prueba gratis y después un saldo prepago. Las cuentas nuevas publican gratis 7 días desde su primera publicación (como mucho 14 días desde el registro); X y los números de teléfono necesitan saldo. Tras la primera recarga, las cuentas conectadas se cobran día a día y el uso (API de X, mensajes, números, llamadas y SMS) según se produce. Se recarga desde el panel. (5 endpoints) [API keys](/reference/api-keys/)Gestiona las API keys. Solo desde el panel, para que una key filtrada no pueda crear otras. (3 endpoints) [Agentes IA](/reference/agents/)Agentes de IA conectados por el servidor MCP (OAuth). El panel los aprueba y los desconecta; los agentes usan https\://api.marsial.dev/mcp. (5 endpoints)
# Grupos de cuentas
> Selecciones de cuentas guardadas, para publicar en todas a la vez.
Selecciones de cuentas guardadas, para publicar en todas a la vez. ## Listar grupos [Sección titulada «Listar grupos»](#listar-grupos) GET`/v1/account-groups` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/account-groups" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/account-groups', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/account-groups",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Crear un grupo [Sección titulada «Crear un grupo»](#crear-un-grupo) POST`/v1/account-groups` #### Cuerpo * `name`stringobligatorio Único en el workspace. máx. 60 * `accountIds`string\[]obligatorio Cuentas de cualquier perfil. máx. 100 elementos #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/account-groups" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/account-groups', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/account-groups",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Editar un grupo [Sección titulada «Editar un grupo»](#editar-un-grupo) PATCH`/v1/account-groups/{id}` #### Parámetros * `id`stringobligatorio #### Cuerpo * `name`string Único en el workspace. máx. 60 * `accountIds`string\[] Cuentas de cualquier perfil. máx. 100 elementos #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/account-groups/grp_4h7j1k" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/account-groups/grp_4h7j1k', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/account-groups/grp_4h7j1k",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Borrar un grupo [Sección titulada «Borrar un grupo»](#borrar-un-grupo) DELETE`/v1/account-groups/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/account-groups/grp_4h7j1k" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/account-groups/grp_4h7j1k', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/account-groups/grp_4h7j1k",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
# Cuentas
> Cuentas sociales conectadas, si pueden publicar, y sus tableros, listas y subreddits.
Cuentas sociales conectadas, si pueden publicar, y sus tableros, listas y subreddits. ## Listar cuentas conectadas [Sección titulada «Listar cuentas conectadas»](#listar-cuentas-conectadas) GET`/v1/accounts` #### Parámetros * `profileId`string #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Ver una cuenta [Sección titulada «Ver una cuenta»](#ver-una-cuenta) GET`/v1/accounts/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Desconectar una cuenta [Sección titulada «Desconectar una cuenta»](#desconectar-una-cuenta) DELETE`/v1/accounts/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/accounts/acc_3k9x2m" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Comprobar si las cuentas pueden publicar [Sección titulada «Comprobar si las cuentas pueden publicar»](#comprobar-si-las-cuentas-pueden-publicar) GET`/v1/accounts/health` Pregunta a cada red en el momento. Las que necesitan reconexión pasan a `needs_reconnection`. #### Parámetros * `profileId`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/health?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/health?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/health?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Comprobar si una cuenta puede publicar [Sección titulada «Comprobar si una cuenta puede publicar»](#comprobar-si-una-cuenta-puede-publicar) GET`/v1/accounts/{id}/health` La misma comprobación que la del perfil, para una cuenta. Los sitios, los CRM y las conexiones de anuncios nunca publican (`canPost: false`). #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/health" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/health', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/health",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar tableros, listas de reproducción, subreddits o flairs [Sección titulada «Listar tableros, listas de reproducción, subreddits o flairs»](#listar-tableros-listas-de-reproducción-subreddits-o-flairs) GET`/v1/accounts/{id}/{kind}` `kind` es `pinterest-boards`, `youtube-playlists`, `reddit-subreddits` o `reddit-flairs` (con `subreddit`). Usa los ids en las opciones del post. #### Parámetros * `id`stringobligatorio * `kind`stringobligatorio Valores: `pinterest-boards` · `youtube-playlists` · `reddit-subreddits` · `reddit-flairs` * `subreddit`string Obligatorio para reddit-flairs. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/{kind}" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/{kind}', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/{kind}",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Qué sincroniza una cuenta de CRM [Sección titulada «Qué sincroniza una cuenta de CRM»](#qué-sincroniza-una-cuenta-de-crm) GET`/v1/accounts/{id}/crm-settings` Las cuentas de HubSpot no publican: convierten a quien escribe a la bandeja del perfil en contactos y guardan cada mensaje en su ficha. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/crm-settings" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/crm-settings', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/crm-settings",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Activar o desactivar la sincronización con el CRM [Sección titulada «Activar o desactivar la sincronización con el CRM»](#activar-o-desactivar-la-sincronización-con-el-crm) PATCH`/v1/accounts/{id}/crm-settings` #### Parámetros * `id`stringobligatorio #### Cuerpo * `syncContacts`boolean Crear un contacto en el CRM por cada persona nueva que escriba. * `logMessages`boolean Guardar cada mensaje de la bandeja en el historial del contacto. #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/accounts/acc_3k9x2m/crm-settings" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/crm-settings', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/crm-settings",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
# Anuncios
> Campañas en Meta, Google, LinkedIn, TikTok, Pinterest, X y Reddit con una conexión de anuncios (plataforma meta-ads, google-ads…): listarlas con gasto y resultados, pausar, reanudar, cambiar presupuestos, promocionar publicaciones, crear campañas y enviar conversiones. Los presupuestos van en unidades enteras de la moneda, nunca en céntimos.
Campañas en Meta, Google, LinkedIn, TikTok, Pinterest, X y Reddit con una conexión de anuncios (plataforma `meta-ads`, `google-ads`…): listarlas con gasto y resultados, pausar, reanudar, cambiar presupuestos, promocionar publicaciones, crear campañas y enviar conversiones. Los presupuestos van en unidades enteras de la moneda, nunca en céntimos. ## Listar cuentas publicitarias [Sección titulada «Listar cuentas publicitarias»](#listar-cuentas-publicitarias) GET`/v1/accounts/{id}/ads/ad-accounts` Las cuentas publicitarias a las que llega una conexión de anuncios. Su id es el adAccountId del resto de llamadas. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/ad-accounts" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/ad-accounts', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/ad-accounts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar campañas con sus resultados [Sección titulada «Listar campañas con sus resultados»](#listar-campañas-con-sus-resultados) GET`/v1/accounts/{id}/ads/campaigns` Las campañas creadas en Marsial y en el administrador de anuncios de la red, con gasto, impresiones y clics del periodo. #### Parámetros * `id`stringobligatorio * `adAccountId`string Solo esta cuenta publicitaria (GET …/ads/ad-accounts). máx. 100 * `from`string Primer día de las métricas (YYYY-MM-DD). Hace 90 días si no lo envías. * `to`string Último día de las métricas (YYYY-MM-DD). Hoy si no lo envías. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns?from=2026-10-01&to=2026-10-31" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns?from=2026-10-01&to=2026-10-31', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns?from=2026-10-01&to=2026-10-31",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Crear una campaña [Sección titulada «Crear una campaña»](#crear-una-campaña) POST`/v1/accounts/{id}/ads/campaigns` Campaña, grupo de anuncios y anuncio en una llamada, en los términos de cada red (adAccountId, goal, budgetAmount, budgetType, la creatividad, la segmentación…): ver la guía de anuncios. Marsial rellena la conexión. #### Parámetros * `id`stringobligatorio #### Cuerpo #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Pausar, reanudar o cambiar el presupuesto [Sección titulada «Pausar, reanudar o cambiar el presupuesto»](#pausar-reanudar-o-cambiar-el-presupuesto) PATCH`/v1/accounts/{id}/ads/campaigns/{campaignId}` Pausar se aplica siempre al momento. Reanudar y cambiar el presupuesto responden 202 cuando el espacio exige aprobación a quien llama. #### Parámetros * `id`stringobligatorio * `campaignId`stringobligatorio #### Cuerpo * `status`string Valores: `active` · `paused` * `budget`object #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns/120210000000" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "paused"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns/120210000000', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"status": "paused"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/campaigns/120210000000",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"status": "paused"
},
)
data = res.json()["data"]
```
## Enviar conversiones [Sección titulada «Enviar conversiones»](#enviar-conversiones) POST`/v1/accounts/{id}/ads/conversions` Eventos desde el servidor para la red: la API de conversiones de Meta, las conversiones offline de Google, LinkedIn y TikTok. #### Parámetros * `id`stringobligatorio #### Cuerpo #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/conversions" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/conversions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/ads/conversions",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Promocionar una publicación [Sección titulada «Promocionar una publicación»](#promocionar-una-publicación) POST`/v1/posts/{id}/boost` Convierte una copia publicada de la publicación (su accountId) en un anuncio pagado por adAccountId. La red lo revisa antes de mostrarlo. #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`stringobligatorio La cuenta de la publicación cuya copia publicada promocionar. * `adAccountId`stringobligatorio La cuenta publicitaria que paga (GET /v1/accounts/{id}/ads/ad-accounts en la conexión de anuncios). máx. 100 * `name`stringobligatorio máx. 200 * `goal`stringobligatorio Lo que optimiza la red. Cada red acepta una parte. Valores: `engagement` · `traffic` · `awareness` · `video_views` · `lead_generation` · `conversions` · `app_promotion` * `budget`objectobligatorio * `startDate`string (date-time) * `endDate`string (date-time) Obligatorio con un presupuesto total. * `targeting`object * `callToAction`string Por ejemplo LEARN_MORE o SHOP_NOW; necesita linkUrl. máx. 50 * `linkUrl`string (uri) #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/boost" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"adAccountId": "act_120210",
"name": "Autumn",
"goal": "traffic",
"budget": {
"amount": 40,
"type": "daily"
}
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/boost', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"adAccountId": "act_120210",
"name": "Autumn",
"goal": "traffic",
"budget": {
"amount": 40,
"type": "daily"
}
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/boost",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"adAccountId": "act_120210",
"name": "Autumn",
"goal": "traffic",
"budget": {
"amount": 40,
"type": "daily"
}
},
)
data = res.json()["data"]
```
## Listar los cambios de anuncios por aprobar [Sección titulada «Listar los cambios de anuncios por aprobar»](#listar-los-cambios-de-anuncios-por-aprobar) GET`/v1/ads/requests` Con `requireAdsApproval` activado, los miembros y los agentes de IA (MCP) piden los cambios de anuncios que gastan dinero en vez de hacerlos. Del más reciente al más antiguo, con lo que pasó con cada uno. #### Parámetros * `status`string Solo los cambios en este estado; si no, todos, del más reciente al más antiguo. Valores: `pending` · `approved` · `rejected` · `failed` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/ads/requests?status=pending" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/ads/requests?status=pending', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/ads/requests?status=pending",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Ver un cambio de anuncios pedido [Sección titulada «Ver un cambio de anuncios pedido»](#ver-un-cambio-de-anuncios-pedido) GET`/v1/ads/requests/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/ads/requests/adr_3m8p2q" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/ads/requests/adr_3m8p2q', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/ads/requests/adr_3m8p2q",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Aprobar o rechazar un cambio de anuncios [Sección titulada «Aprobar o rechazar un cambio de anuncios»](#aprobar-o-rechazar-un-cambio-de-anuncios) POST`/v1/ads/requests/{id}/review` Propietarios y admins (y claves API). Al aprobar se envía a la red en el momento; si la red lo rechaza, la solicitud queda `failed` con el motivo. Los agentes de IA no pueden revisar. #### Parámetros * `id`stringobligatorio #### Cuerpo * `decision`stringobligatorio `approve` envía el cambio a la red en el momento; `reject` lo descarta. Valores: `approve` · `reject` * `note`string Por qué, para quien lo pidió. máx. 1000 #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/ads/requests/adr_3m8p2q/review" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "approve"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/ads/requests/adr_3m8p2q/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"decision": "approve"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/ads/requests/adr_3m8p2q/review",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"decision": "approve"
},
)
data = res.json()["data"]
```
# Agentes IA
> Agentes de IA conectados por el servidor MCP (OAuth). El panel los aprueba y los desconecta; los agentes usan https://api.marsial.dev/mcp.
Agentes de IA conectados por el servidor MCP (OAuth). El panel los aprueba y los desconecta; los agentes usan . ## Ver quién pide acceso [Sección titulada «Ver quién pide acceso»](#ver-quién-pide-acceso) GET`/v1/oauth/requests/{id}` Solo desde el panel. El id llega en el parámetro `request` de la página de permiso; las solicitudes duran 10 minutos. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/oauth/requests/authz_…" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/oauth/requests/authz_…', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/oauth/requests/authz_…",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Dejar entrar al agente [Sección titulada «Dejar entrar al agente»](#dejar-entrar-al-agente) POST`/v1/oauth/requests/{id}/approve` Solo desde el panel. El agente actúa como quien lo aprueba, con su rol, hasta que se desconecte. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/oauth/requests/authz_…/approve" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/oauth/requests/authz_…/approve', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/oauth/requests/authz_…/approve",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Rechazar al agente [Sección titulada «Rechazar al agente»](#rechazar-al-agente) POST`/v1/oauth/requests/{id}/deny` Solo desde el panel. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/oauth/requests/authz_…/deny" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/oauth/requests/authz_…/deny', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/oauth/requests/authz_…/deny",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar los agentes conectados [Sección titulada «Listar los agentes conectados»](#listar-los-agentes-conectados) GET`/v1/oauth/grants` Solo desde el panel. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/oauth/grants" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/oauth/grants', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/oauth/grants",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Desconectar un agente [Sección titulada «Desconectar un agente»](#desconectar-un-agente) DELETE`/v1/oauth/grants/{id}` Solo desde el panel. Sus tokens dejan de funcionar al momento. Cada miembro desconecta los suyos; propietarios y admins, cualquiera. #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/oauth/grants/grt_5k2j8h" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/oauth/grants/grt_5k2j8h', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/oauth/grants/grt_5k2j8h",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
# Analíticas
> Seguidores, totales diarios, mejores horas para publicar y mejores publicaciones, por perfil o por cuenta.
Seguidores, totales diarios, mejores horas para publicar y mejores publicaciones, por perfil o por cuenta. ## Seguidores y crecimiento [Sección titulada «Seguidores y crecimiento»](#seguidores-y-crecimiento) GET`/v1/analytics/followers` Seguidores actuales, crecimiento en el periodo e histórico diario de cada cuenta. Se actualiza una vez al día. #### Parámetros * `profileId`stringobligatorio * `accountId`string Solo esta cuenta; si no, todo el perfil. * `from`string Primer día (YYYY-MM-DD). Por defecto, hace 30 días. * `to`string Último día (YYYY-MM-DD). Por defecto, hoy. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/analytics/followers" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/analytics/followers', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/analytics/followers",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Totales diarios [Sección titulada «Totales diarios»](#totales-diarios) GET`/v1/analytics/daily` Publicaciones e interacción por día (contada el día que llega) y totales por red. #### Parámetros * `profileId`stringobligatorio * `accountId`string Solo esta cuenta; si no, todo el perfil. * `from`string Primer día (YYYY-MM-DD). Por defecto, hace 30 días. * `to`string Último día (YYYY-MM-DD). Por defecto, hoy. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/analytics/daily" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/analytics/daily', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/analytics/daily",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Mejores horas para publicar [Sección titulada «Mejores horas para publicar»](#mejores-horas-para-publicar) GET`/v1/analytics/best-times` Interacción media por día de la semana y hora, a partir de las publicaciones de la cuenta. #### Parámetros * `profileId`stringobligatorio * `accountId`string Solo esta cuenta; si no, todo el perfil. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/analytics/best-times" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/analytics/best-times', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/analytics/best-times",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Mejores publicaciones [Sección titulada «Mejores publicaciones»](#mejores-publicaciones) GET`/v1/analytics/top-posts` Publicaciones del periodo por interacción (o por fecha), también las publicadas fuera de Marsial. #### Parámetros * `profileId`stringobligatorio * `accountId`string Solo esta cuenta; si no, todo el perfil. * `from`string Primer día (YYYY-MM-DD). Por defecto, hace 30 días. * `to`string Último día (YYYY-MM-DD). Por defecto, hoy. * `sortBy`string Valores: `engagement` · `date` * `limit`integer máx. 50 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/analytics/top-posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/analytics/top-posts', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/analytics/top-posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
# API keys
> Gestiona las API keys. Solo desde el panel, para que una key filtrada no pueda crear otras.
Gestiona las API keys. Solo desde el panel, para que una key filtrada no pueda crear otras. ## Listar API keys [Sección titulada «Listar API keys»](#listar-api-keys) GET`/v1/api-keys`Solo desde el panel #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/api-keys" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/api-keys', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/api-keys",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Crear una API key [Sección titulada «Crear una API key»](#crear-una-api-key) POST`/v1/api-keys`Solo desde el panel #### Cuerpo * `name`stringobligatorio máx. 60 #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/api-keys" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "production"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/api-keys', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "production"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/api-keys",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"name": "production"
},
)
data = res.json()["data"]
```
## Revocar una API key [Sección titulada «Revocar una API key»](#revocar-una-api-key) DELETE`/v1/api-keys/{id}`Solo desde el panel #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/api-keys/key_2b4n6m" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/api-keys/key_2b4n6m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/api-keys/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
# Automatizaciones
> Comentario a mensaje: a quien comente una palabra clave, se le responde con un mensaje privado (Instagram, Facebook) o en público (todas las redes).
Comentario a mensaje: a quien comente una palabra clave, se le responde con un mensaje privado (Instagram, Facebook) o en público (todas las redes). ## Listar automatizaciones [Sección titulada «Listar automatizaciones»](#listar-automatizaciones) GET`/v1/automations` #### Parámetros * `profileId`stringobligatorio * `accountId`string #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/automations" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/automations', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/automations",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Crear una automatización [Sección titulada «Crear una automatización»](#crear-una-automatización) POST`/v1/automations` En Instagram y Facebook envía `dmMessage` (con hasta 3 botones) a quien comente una palabra clave; en TikTok, Threads, LinkedIn y YouTube publica `commentReply`. Sin publicación, vigila todas las de la cuenta. #### Cuerpo * `name`stringobligatorio máx. 100 * `trigger`string `story_reply`: respuestas a una story de Instagram. Valores: `comment` · `story_reply`Por defecto: `"comment"` * `postId`string | null Una publicación de Marsial que vigilar. * `inboxPostId`string | null O una publicación tal como la lista GET /v1/inbox/posts. Ninguna: todas. * `keywords`string\[] Vacío: cualquier comentario la activa. Por defecto: `[]`máx. 50 elementos * `matchMode`string Valores: `contains` · `word` · `exact`Por defecto: `"contains"` * `excludeKeywords`string\[] Por defecto: `[]`máx. 50 elementos * `dmMessage`string Mensaje privado a quien comenta. Solo Instagram y Facebook, y obligatorio en ellas. máx. 1000 * `buttons`object\[] Hasta 3 botones bajo el mensaje. Por defecto: `[]`máx. 3 elementos * `commentReply`string Respuesta pública al comentario. Obligatoria en TikTok, Threads, LinkedIn y YouTube. máx. 2000 * `dmDelaySeconds`integer máx. 86.400 * `repeat`string `once`: un mensaje por persona. Valores: `once` · `every_comment`Por defecto: `"once"` * `likeComment`boolean Por defecto: `false` * `hideComment`boolean Por defecto: `false` * `active`boolean Por defecto: `true` * `accountId`stringobligatorio Cuenta de Instagram, Facebook, TikTok, Threads, LinkedIn o YouTube. #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/automations" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/automations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/automations",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Ver una automatización [Sección titulada «Ver una automatización»](#ver-una-automatización) GET`/v1/automations/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/automations/aut_6r3e9w" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/automations/aut_6r3e9w', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/automations/aut_6r3e9w",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Editar o pausar una automatización [Sección titulada «Editar o pausar una automatización»](#editar-o-pausar-una-automatización) PATCH`/v1/automations/{id}` Lo que no envíes se mantiene. `active: false` la pausa. #### Parámetros * `id`stringobligatorio #### Cuerpo * `name`string máx. 100 * `trigger`string `story_reply`: respuestas a una story de Instagram. Valores: `comment` · `story_reply` * `postId`string | null Una publicación de Marsial que vigilar. * `inboxPostId`string | null O una publicación tal como la lista GET /v1/inbox/posts. Ninguna: todas. * `keywords`string\[] Vacío: cualquier comentario la activa. máx. 50 elementos * `matchMode`string Valores: `contains` · `word` · `exact` * `excludeKeywords`string\[] máx. 50 elementos * `dmMessage`string Mensaje privado a quien comenta. Solo Instagram y Facebook, y obligatorio en ellas. máx. 1000 * `buttons`object\[] Hasta 3 botones bajo el mensaje. máx. 3 elementos * `commentReply`string Respuesta pública al comentario. Obligatoria en TikTok, Threads, LinkedIn y YouTube. máx. 2000 * `dmDelaySeconds`integer máx. 86.400 * `repeat`string `once`: un mensaje por persona. Valores: `once` · `every_comment` * `likeComment`boolean * `hideComment`boolean * `active`boolean #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/automations/aut_6r3e9w" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/automations/aut_6r3e9w', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/automations/aut_6r3e9w",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Borrar una automatización [Sección titulada «Borrar una automatización»](#borrar-una-automatización) DELETE`/v1/automations/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/automations/aut_6r3e9w" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/automations/aut_6r3e9w', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/automations/aut_6r3e9w",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Qué ha hecho una automatización [Sección titulada «Qué ha hecho una automatización»](#qué-ha-hecho-una-automatización) GET`/v1/automations/{id}/logs` Cada comentario que la activó, el más reciente primero, con el resultado del mensaje. #### Parámetros * `id`stringobligatorio * `skip`integer máx. 9.007.199.254.740.991 * `limit`integer máx. 100 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/automations/aut_6r3e9w/logs" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/automations/aut_6r3e9w/logs', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/automations/aut_6r3e9w/logs",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
# Facturación
> Una prueba gratis y después un saldo prepago. Las cuentas nuevas publican gratis 7 días desde su primera publicación (como mucho 14 días desde el registro); X y los números de teléfono necesitan saldo. Tras la primera recarga, las cuentas conectadas se cobran día a día y el uso (API de X, mensajes, números, llamadas y SMS) según se produce. Se recarga desde el panel.
Una prueba gratis y después un saldo prepago. Las cuentas nuevas publican gratis 7 días desde su primera publicación (como mucho 14 días desde el registro); X y los números de teléfono necesitan saldo. Tras la primera recarga, las cuentas conectadas se cobran día a día y el uso (API de X, mensajes, números, llamadas y SMS) según se produce. Se recarga desde el panel. ## Ver el saldo [Sección titulada «Ver el saldo»](#ver-el-saldo) GET`/v1/billing` Saldo, prueba gratis, cuentas conectadas y lo que cuestan. Cuando la prueba termina sin recarga, o el saldo se agota después de pagar, conectar cuentas y publicar o enviar responden 402; las publicaciones programadas de una prueba terminada esperan como `paused` hasta la primera recarga. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/billing" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/billing', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/billing",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar los movimientos del saldo [Sección titulada «Listar los movimientos del saldo»](#listar-los-movimientos-del-saldo) GET`/v1/billing/movements` Recargas y cargos, del más reciente al más antiguo. #### Parámetros * `limit`integer máx. 200 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/billing/movements" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/billing/movements', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/billing/movements",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Añadir saldo [Sección titulada «Añadir saldo»](#añadir-saldo) POST`/v1/billing/top-up`Solo desde el panel Abre una página de pago. El saldo sube cuando el pago se completa, y la tarjeta queda guardada para las recargas automáticas. #### Cuerpo * `amount`integerobligatorio Saldo que añadir, en céntimos (impuestos aparte, si los hay). Los límites vienen en GET /v1/billing. máx. 9.007.199.254.740.991 * `successUrl`string (uri)obligatorio Página del panel a la que volver tras pagar. * `cancelUrl`string (uri)obligatorio Página del panel a la que volver si el usuario sale de Checkout. #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/billing/top-up" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/billing/top-up', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/billing/top-up",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Configurar la recarga automática [Sección titulada «Configurar la recarga automática»](#configurar-la-recarga-automática) PUT`/v1/billing/auto-recharge`Solo desde el panel Recarga la tarjeta guardada cuando el saldo baja del umbral, hasta un máximo al mes. Necesita una recarga previa. #### Cuerpo * `enabled`booleanobligatorio * `threshold`integerobligatorio Recargar cuando el saldo baje de esto, en céntimos. máx. 9.007.199.254.740.991 * `amount`integerobligatorio Lo que añade cada recarga, en céntimos. máx. 9.007.199.254.740.991 * `monthlyLimit`integerobligatorio Máximo que pueden añadir las recargas automáticas en un mes natural, en céntimos. máx. 9.007.199.254.740.991 #### Respuesta 200 * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/billing/auto-recharge" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/billing/auto-recharge', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/billing/auto-recharge",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Abrir el portal de facturación [Sección titulada «Abrir el portal de facturación»](#abrir-el-portal-de-facturación) POST`/v1/billing/portal`Solo desde el panel Facturas y método de pago guardado. #### Cuerpo * `returnUrl`string (uri)obligatorio Página del panel a la que volver. #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/billing/portal" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/billing/portal', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/billing/portal",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
# Blogs
> Artículos en sitios de WordPress, Shopify, Wix y Webflow: listar, crear borradores, programar, publicar, cambiar y borrar. Estas cuentas reciben artículos, no publicaciones.
Artículos en sitios de WordPress, Shopify, Wix y Webflow: listar, crear borradores, programar, publicar, cambiar y borrar. Estas cuentas reciben artículos, no publicaciones. ## Listar los blogs de un sitio [Sección titulada «Listar los blogs de un sitio»](#listar-los-blogs-de-un-sitio) GET`/v1/accounts/{id}/blogs` Una tienda Shopify puede tener varios blogs y un sitio de Webflow uno por cada colección del CMS con un campo de texto enriquecido; WordPress y Wix tienen uno. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar artículos [Sección titulada «Listar artículos»](#listar-artículos) GET`/v1/accounts/{id}/blogs/{blogId}/articles` Publicados, programados, borradores y, en WordPress, pendientes y privados. #### Parámetros * `id`stringobligatorio * `blogId`stringobligatorio * `cursor`string máx. 4000 * `limit`integer máx. 50 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles?limit=20" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles?limit=20', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles?limit=20",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Crear un artículo [Sección titulada «Crear un artículo»](#crear-un-artículo) POST`/v1/accounts/{id}/blogs/{blogId}/articles` Queda en borrador salvo que envíes `isPublished: true`; con una `publishDate` futura el sitio lo programa. El sitio descarga la imagen desde su URL (súbela antes con POST /media/upload-url). `seo` funciona en Shopify y Wix; `fields` rellena los campos propios de una colección de Webflow. #### Parámetros * `id`stringobligatorio * `blogId`stringobligatorio #### Cuerpo * `title`stringobligatorio máx. 500 * `bodyHtml`string El artículo en HTML. máx. 500.000 * `handle`string Slug de la URL. Si no lo envías, se crea a partir del título. máx. 255 * `excerpt`string máx. 5000 * `tags`string\[] Sustituye la lista entera; las etiquetas que no existan se crean. máx. 100 elementos * `author`string WordPress: el id de un usuario. Shopify: un nombre visible. Webflow: el id del elemento autor. máx. 200 * `image`object Imagen destacada desde una URL pública (por ejemplo, de POST /v1/media/upload-url). * `seo`object Solo en Shopify y Wix. * `isPublished`boolean false lo deja en borrador. * `publishDate`string (date-time) Una fecha futura lo programa. * `fields`object Solo en Webflow: los campos propios de la colección, por su slug. #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Our autumn collection",
"bodyHtml": "The first pieces land next month.
",
"excerpt": "An early look at what is arriving.",
"tags": [
"autumn",
"new arrivals"
],
"image": {
"url": "https://cdn.acme.com/autumn.jpg",
"altText": "Wool coats on a rail"
},
"isPublished": true,
"publishDate": "2026-11-03T09:00:00+01:00"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"title": "Our autumn collection",
"bodyHtml": "The first pieces land next month.
",
"excerpt": "An early look at what is arriving.",
"tags": [
"autumn",
"new arrivals"
],
"image": {
"url": "https://cdn.acme.com/autumn.jpg",
"altText": "Wool coats on a rail"
},
"isPublished": true,
"publishDate": "2026-11-03T09:00:00+01:00"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"title": "Our autumn collection",
"bodyHtml": "The first pieces land next month.
",
"excerpt": "An early look at what is arriving.",
"tags": [
"autumn",
"new arrivals"
],
"image": {
"url": "https://cdn.acme.com/autumn.jpg",
"altText": "Wool coats on a rail"
},
"isPublished": True,
"publishDate": "2026-11-03T09:00:00+01:00"
},
)
data = res.json()["data"]
```
## Obtener un artículo [Sección titulada «Obtener un artículo»](#obtener-un-artículo) GET`/v1/accounts/{id}/blogs/{blogId}/articles/{articleId}` #### Parámetros * `id`stringobligatorio * `blogId`stringobligatorio * `articleId`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Cambiar, publicar o despublicar un artículo [Sección titulada «Cambiar, publicar o despublicar un artículo»](#cambiar-publicar-o-despublicar-un-artículo) PATCH`/v1/accounts/{id}/blogs/{blogId}/articles/{articleId}` Los campos que no envíes se quedan como están. `tags` sustituye la lista entera. `isPublished: false` lo devuelve a borrador. #### Parámetros * `id`stringobligatorio * `blogId`stringobligatorio * `articleId`stringobligatorio #### Cuerpo * `title`string máx. 500 * `bodyHtml`string El artículo en HTML. máx. 500.000 * `handle`string Slug de la URL. Si no lo envías, se crea a partir del título. máx. 255 * `excerpt`string máx. 5000 * `tags`string\[] Sustituye la lista entera; las etiquetas que no existan se crean. máx. 100 elementos * `author`string WordPress: el id de un usuario. Shopify: un nombre visible. Webflow: el id del elemento autor. máx. 200 * `image`object Imagen destacada desde una URL pública (por ejemplo, de POST /v1/media/upload-url). * `seo`object Solo en Shopify y Wix. * `isPublished`boolean false lo deja en borrador. * `publishDate`string (date-time) Una fecha futura lo programa. * `fields`object Solo en Webflow: los campos propios de la colección, por su slug. #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"isPublished": false
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"isPublished": false
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"isPublished": False
},
)
data = res.json()["data"]
```
## Borrar un artículo [Sección titulada «Borrar un artículo»](#borrar-un-artículo) DELETE`/v1/accounts/{id}/blogs/{blogId}/articles/{articleId}` #### Parámetros * `id`stringobligatorio * `blogId`stringobligatorio * `articleId`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/blogs/1/articles/1842",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
# Llamadas
> Llama desde tus números (Marsial llama a la persona y la conecta con tu teléfono, una dirección SIP o un agente de voz con IA), lee el historial con grabaciones y transcripciones y calcula lo que cuesta una llamada.
Llama desde tus números (Marsial llama a la persona y la conecta con tu teléfono, una dirección SIP o un agente de voz con IA), lee el historial con grabaciones y transcripciones y calcula lo que cuesta una llamada. ## Historial de llamadas de un número [Sección titulada «Historial de llamadas de un número»](#historial-de-llamadas-de-un-número) GET`/v1/phone-numbers/{id}/calls` Entrantes y salientes, de la más reciente a la más antigua. #### Parámetros * `id`stringobligatorio * `cursor`string * `direction`string Valores: `inbound` · `outbound` * `limit`integer máx. 100 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/num_…/calls" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/calls', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/num_…/calls",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Llamar a alguien [Sección titulada «Llamar a alguien»](#llamar-a-alguien) POST`/v1/calls` Marsial llama a `to` desde tu número y, cuando contesta, le conecta con `forwardTo` (tu teléfono, una dirección SIP o un agente de voz) o con el destino de entrada del número. #### Cuerpo * `numberId`stringobligatorio El número que llama (num\_…). * `to`stringobligatorio A quién llamar. * `forwardTo`string Con quién conectarle cuando conteste; si no, el destino de entrada del número. máx. 500 * `greeting`string Se le dice al contestar, antes de conectar. máx. 500 * `record`boolean * `transcribe`boolean * `idempotencyKey`string máx. 100 #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/calls" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"numberId": "num_…",
"to": "+447700900123",
"forwardTo": "tel:+447700900456"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/calls', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"numberId": "num_…",
"to": "+447700900123",
"forwardTo": "tel:+447700900456"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/calls",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"numberId": "num_…",
"to": "+447700900123",
"forwardTo": "tel:+447700900456"
},
)
data = res.json()["data"]
```
## Lo que costaría una llamada [Sección titulada «Lo que costaría una llamada»](#lo-que-costaría-una-llamada) GET`/v1/calls/estimate` #### Parámetros * `to`stringobligatorio * `minutes`integer Por defecto: `5`máx. 600 * `numberId`string El número que llamaría: la respuesta dice además si puede llegar a `to`. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/calls/estimate?to=%2B447700900123&minutes=5" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/calls/estimate?to=%2B447700900123&minutes=5', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/calls/estimate?to=%2B447700900123&minutes=5",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Ver una llamada [Sección titulada «Ver una llamada»](#ver-una-llamada) GET`/v1/calls/{id}` Con su transcripción si la transcripción estaba activada. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/calls/call_…" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/calls/call_…', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/calls/call_…",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Grabación de una llamada [Sección titulada «Grabación de una llamada»](#grabación-de-una-llamada) GET`/v1/calls/{id}/recording` Un enlace al MP3 que funciona 15 minutos. Solo llamadas grabadas (por ajuste o por llamada). #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/calls/call_…/recording" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/calls/call_…/recording', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/calls/call_…/recording",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Colgar [Sección titulada «Colgar»](#colgar) POST`/v1/calls/{id}/end` #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X POST "https://api.marsial.dev/v1/calls/call_…/end" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/calls/call_…/end', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/calls/call_…/end",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Transferir una llamada en curso [Sección titulada «Transferir una llamada en curso»](#transferir-una-llamada-en-curso) POST`/v1/calls/{id}/transfer` A otro teléfono (+E164) o a una dirección SIP; la llamada sale de tu control. #### Parámetros * `id`stringobligatorio #### Cuerpo * `to`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X POST "https://api.marsial.dev/v1/calls/call_…/transfer" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+447700900789"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/calls/call_…/transfer', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"to": "+447700900789"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/calls/call_…/transfer",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"to": "+447700900789"
},
)
data = res.json()["data"]
```
# Conexión
> Conecta una cuenta social o un sitio: manda al usuario a la URL y Marsial lo devuelve a tu redirectUrl.
Conecta una cuenta social o un sitio: manda al usuario a la URL y Marsial lo devuelve a tu redirectUrl. ## Empezar a conectar una cuenta [Sección titulada «Empezar a conectar una cuenta»](#empezar-a-conectar-una-cuenta) GET`/v1/connect/{platform}` Devuelve la URL a la que mandar al usuario. Al terminar, Marsial vuelve a `redirectUrl` con `connected=&accountId=…`, con `error=…` si falló, o con `select=` cuando el usuario debe elegir página, organización, tablero, ficha o perfil (Facebook, LinkedIn, Pinterest, Google Business, Snapchat) un canal (Slack) o un número (WhatsApp). Shopify necesita `shop` (el dominio myshopify.com de la tienda). `wordpress` aquí conecta sitios de WordPress.com; los autoalojados usan POST /connect/wordpress. Las conexiones de anuncios (`meta-ads`, `google-ads`…) también empiezan aquí. #### Parámetros * `platform`stringobligatorio * `profileId`stringobligatorio El perfil al que pertenecerá la cuenta. * `redirectUrl`string (uri)obligatorio A dónde vuelve el usuario cuando termina la conexión. * `shop`string Solo para Shopify, y ahí obligatorio: el dominio myshopify.com de la tienda (o su prefijo). #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Conectar un WordPress autoalojado [Sección titulada «Conectar un WordPress autoalojado»](#conectar-un-wordpress-autoalojado) POST`/v1/connect/wordpress` Un WordPress autoalojado no tiene OAuth: crea una contraseña de aplicación en el perfil de WordPress del usuario que publicará (Usuarios → Perfil → Contraseñas de aplicación) y envíala con su nombre de usuario. Marsial comprueba el sitio y los permisos antes de guardarlo. Marsial no guarda la contraseña; revócala en WordPress para cortar el acceso. #### Cuerpo * `profileId`stringobligatorio El perfil al que pertenecerá el sitio. * `siteUrl`string (starts_with)obligatorio La raíz pública del sitio, por ejemplo https\://example.com. * `username`stringobligatorio El nombre de usuario de WordPress de quien publicará. máx. 200 * `applicationPassword`stringobligatorio Una contraseña de aplicación creada en el perfil de WordPress de ese usuario. mín. 8máx. 200 #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/connect/wordpress" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profileId": "prf_8f2k4d",
"siteUrl": "https://blog.acme.com",
"username": "editor",
"applicationPassword": "abcd efgh ijkl mnop qrst uvwx"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/wordpress', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"profileId": "prf_8f2k4d",
"siteUrl": "https://blog.acme.com",
"username": "editor",
"applicationPassword": "abcd efgh ijkl mnop qrst uvwx"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/connect/wordpress",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"profileId": "prf_8f2k4d",
"siteUrl": "https://blog.acme.com",
"username": "editor",
"applicationPassword": "abcd efgh ijkl mnop qrst uvwx"
},
)
data = res.json()["data"]
```
## Listar lo que el usuario puede elegir [Sección titulada «Listar lo que el usuario puede elegir»](#listar-lo-que-el-usuario-puede-elegir) GET`/v1/connect/sessions/{id}/options` El `id` es el valor de `select` que Marsial añadió a tu redirectUrl. Las sesiones caducan a la hora. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/options" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/options', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/options",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Elegir una opción y terminar la conexión [Sección titulada «Elegir una opción y terminar la conexión»](#elegir-una-opción-y-terminar-la-conexión) POST`/v1/connect/sessions/{id}/select` #### Parámetros * `id`stringobligatorio #### Cuerpo * `optionId`stringobligatorio máx. 200 #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/select" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"optionId": "1042…"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/select', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"optionId": "1042…"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/connect/sessions/cs_5t2y8u/select",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"optionId": "1042…"
},
)
data = res.json()["data"]
```
# Bandeja
> Mensajes directos, comentarios y reseñas de las cuentas de un perfil. Los listados piden el perfil; las acciones, la cuenta a la que pertenece cada elemento.
Mensajes directos, comentarios y reseñas de las cuentas de un perfil. Los listados piden el perfil; las acciones, la cuenta a la que pertenece cada elemento. ## Listar conversaciones [Sección titulada «Listar conversaciones»](#listar-conversaciones) GET`/v1/inbox/conversations` Mensajes directos de Facebook, Instagram, X, Bluesky, Reddit y Telegram, los más recientes primero. #### Parámetros * `profileId`stringobligatorio * `accountId`string * `status`string Valores: `active` · `archived` * `cursor`string El nextCursor de la página anterior. máx. 4000 * `limit`integer máx. 100 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/inbox/conversations" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/conversations",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar los mensajes de una conversación [Sección titulada «Listar los mensajes de una conversación»](#listar-los-mensajes-de-una-conversación) GET`/v1/inbox/conversations/{id}/messages` #### Parámetros * `id`stringobligatorio * `accountId`string Solo para ids de conversación anteriores al 27 de octubre de 2026: los nuevos ya llevan su cuenta. * `cursor`string El nextCursor de la página anterior. máx. 4000 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Enviar un mensaje [Sección titulada «Enviar un mensaje»](#enviar-un-mensaje) POST`/v1/inbox/conversations/{id}/messages` Texto, un adjunto o ambos. Meta solo deja responder durante las 24 horas siguientes al último mensaje de la persona. #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`string Solo para ids de conversación anteriores al 27 de octubre de 2026: los nuevos ya llevan su cuenta. * `text`string máx. 4000 * `attachmentUrl`string (uri) Una URL https pública (por ejemplo, de POST /v1/media/upload-url). * `attachmentType`string Valores: `image` · `video` · `audio` · `file` #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/conversations/cnv_…/messages",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Marcar una conversación como leída [Sección titulada «Marcar una conversación como leída»](#marcar-una-conversación-como-leída) POST`/v1/inbox/conversations/{id}/read` #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`string Solo para ids de conversación anteriores al 27 de octubre de 2026: los nuevos ya llevan su cuenta. #### Respuesta 204 Sin contenido * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/conversations/cnv_…/read" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations/cnv_…/read', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/conversations/cnv_…/read",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Archivar o recuperar una conversación [Sección titulada «Archivar o recuperar una conversación»](#archivar-o-recuperar-una-conversación) PATCH`/v1/inbox/conversations/{id}` #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`string Solo para ids de conversación anteriores al 27 de octubre de 2026: los nuevos ya llevan su cuenta. * `status`stringobligatorio Valores: `active` · `archived` #### Respuesta 204 Sin contenido * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/inbox/conversations/cnv_…" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations/cnv_…', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/inbox/conversations/cnv_…",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar publicaciones con comentarios [Sección titulada «Listar publicaciones con comentarios»](#listar-publicaciones-con-comentarios) GET`/v1/inbox/posts` Publicaciones recientes de las cuentas del perfil con su número de comentarios, también las publicadas fuera de Marsial. #### Parámetros * `profileId`stringobligatorio * `accountId`string * `cursor`string El nextCursor de la página anterior. máx. 4000 * `limit`integer máx. 100 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/inbox/posts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/posts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/posts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar los comentarios de una publicación [Sección titulada «Listar los comentarios de una publicación»](#listar-los-comentarios-de-una-publicación) GET`/v1/inbox/posts/{id}/comments` #### Parámetros * `id`stringobligatorio * `accountId`stringobligatorio La cuenta a la que pertenece. * `cursor`string El nextCursor de la página anterior. máx. 4000 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/inbox/posts/thr_…/comments" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/posts/thr_…/comments', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/posts/thr_…/comments",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Comentar o responder a un comentario [Sección titulada «Comentar o responder a un comentario»](#comentar-o-responder-a-un-comentario) POST`/v1/inbox/posts/{id}/comments` #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`stringobligatorio La cuenta a la que pertenece. * `text`stringobligatorio máx. 8000 * `commentId`string Responder bajo este comentario; sin él, se comenta en la publicación. #### Respuesta 204 Sin contenido * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/posts/thr_…/comments" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"text": "Thank you!"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/posts/thr_…/comments', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"text": "Thank you!"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/posts/thr_…/comments",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"text": "Thank you!"
},
)
data = res.json()["data"]
```
## Ocultar un comentario o darle me gusta [Sección titulada «Ocultar un comentario o darle me gusta»](#ocultar-un-comentario-o-darle-me-gusta) PATCH`/v1/inbox/posts/{id}/comments/{commentId}` Cada comentario indica en `can` lo que permite su red. #### Parámetros * `id`stringobligatorio * `commentId`stringobligatorio #### Cuerpo * `accountId`stringobligatorio La cuenta a la que pertenece. * `hidden`boolean * `liked`boolean #### Respuesta 204 Sin contenido * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/inbox/posts/thr_…/comments/cmt_…" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/posts/thr_…/comments/cmt_…', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/inbox/posts/thr_…/comments/cmt_…",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Borrar un comentario [Sección titulada «Borrar un comentario»](#borrar-un-comentario) DELETE`/v1/inbox/posts/{id}/comments/{commentId}` #### Parámetros * `id`stringobligatorio * `commentId`stringobligatorio * `accountId`stringobligatorio La cuenta a la que pertenece. #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/inbox/posts/thr_…/comments/cmt_…" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/inbox/posts/thr_…/comments/cmt_…', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/inbox/posts/thr_…/comments/cmt_…",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Listar menciones [Sección titulada «Listar menciones»](#listar-menciones) GET`/v1/inbox/mentions` Publicaciones y comentarios de otros que etiquetan las cuentas del perfil, de los últimos 7 días: Instagram (cuentas conectadas con Facebook) y páginas de LinkedIn. #### Parámetros * `profileId`stringobligatorio * `accountId`string * `cursor`string El nextCursor de la página anterior. máx. 4000 * `limit`integer máx. 100 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/inbox/mentions?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/mentions?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/mentions?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Responder a una mención [Sección titulada «Responder a una mención»](#responder-a-una-mención) POST`/v1/inbox/mentions/{id}/reply` Solo Instagram (`canReply`): responde bajo el comentario que etiquetó a la cuenta o comenta en la publicación cuyo texto la etiquetó. #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`stringobligatorio La cuenta a la que pertenece. * `text`stringobligatorio máx. 2200 #### Respuesta 204 Sin contenido * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/mentions/mtn_…/reply" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"text": "Thanks for the shout-out!"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/mentions/mtn_…/reply', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"text": "Thanks for the shout-out!"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/mentions/mtn_…/reply",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"text": "Thanks for the shout-out!"
},
)
data = res.json()["data"]
```
## Listar reseñas [Sección titulada «Listar reseñas»](#listar-reseñas) GET`/v1/inbox/reviews` Reseñas de Google Business y de Facebook, con su total y la valoración media. #### Parámetros * `profileId`stringobligatorio * `accountId`string * `cursor`string El nextCursor de la página anterior. máx. 4000 * `limit`integer máx. 100 * `hasReply`string Solo reseñas con respuesta (true) o sin ella (false). Valores: `true` · `false` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/inbox/reviews" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/reviews', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/inbox/reviews",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Responder a una reseña [Sección titulada «Responder a una reseña»](#responder-a-una-reseña) POST`/v1/inbox/reviews/{id}/reply` #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`stringobligatorio La cuenta a la que pertenece. * `text`stringobligatorio máx. 4000 #### Respuesta 204 Sin contenido * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/reviews/rev_…/reply" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/reviews/rev_…/reply', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/reviews/rev_…/reply",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Borrar la respuesta a una reseña [Sección titulada «Borrar la respuesta a una reseña»](#borrar-la-respuesta-a-una-reseña) DELETE`/v1/inbox/reviews/{id}/reply` Solo en Google Business. #### Parámetros * `id`stringobligatorio * `accountId`stringobligatorio La cuenta a la que pertenece. #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/inbox/reviews/rev_…/reply" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/inbox/reviews/rev_…/reply', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/inbox/reviews/rev_…/reply",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
# Multimedia
> Sube imágenes y vídeos a Marsial antes de publicarlos.
Sube imágenes y vídeos a Marsial antes de publicarlos. ## Pedir una URL de subida [Sección titulada «Pedir una URL de subida»](#pedir-una-url-de-subida) POST`/v1/media/upload-url` JPEG, PNG, WebP y GIF hasta 20 MB; MP4, MOV y WebM hasta 1 GB. Sube el archivo con PUT a `uploadUrl` y usa `publicUrl` en el post. #### Cuerpo * `filename`stringobligatorio máx. 255 * `contentType`stringobligatorio mín. 3 * `size`integerobligatorio máx. 9.007.199.254.740.991 #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/media/upload-url" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "autumn.mp4",
"contentType": "video/mp4",
"size": 48211234
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/media/upload-url', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"filename": "autumn.mp4",
"contentType": "video/mp4",
"size": 48211234
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/media/upload-url",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"filename": "autumn.mp4",
"contentType": "video/mp4",
"size": 48211234
},
)
data = res.json()["data"]
```
# Números de teléfono
> Números para llamadas y SMS: países y precios, comprar uno (los países que regulan los números piden antes la identidad del titular: KYC), decidir a dónde van las llamadas y activar los SMS. Los gestionan propietarios y admins; cada número se cobra al mes del saldo.
Números para llamadas y SMS: países y precios, comprar uno (los países que regulan los números piden antes la identidad del titular: KYC), decidir a dónde van las llamadas y activar los SMS. Los gestionan propietarios y admins; cada número se cobra al mes del saldo. ## Países y precios [Sección titulada «Países y precios»](#países-y-precios) GET`/v1/phone-numbers/countries` Dónde se pueden comprar números, por tipo: precio al mes (céntimos), si hace falta KYC, SMS y existencias. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/countries" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/countries', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/countries",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Buscar números disponibles [Sección titulada «Buscar números disponibles»](#buscar-números-disponibles) GET`/v1/phone-numbers/available` Existencias del país en directo. Cualquier resultado se puede comprar tal cual con POST /phone-numbers (salvo en países con KYC). #### Parámetros * `country`stringobligatorio ISO 3166-1 alfa-2 (GET /v1/phone-numbers/countries). * `numberType`string local, mobile, national o toll_free; si no se envía, el del país por defecto. Valores: `local` · `mobile` · `national` · `toll_free` * `areaCode`string Prefijo (91, 415) o nombre de una ciudad. máx. 40 * `locality`string Una ciudad del país. máx. 80 * `contains`string Dígitos que debe contener el número. * `sms`string Solo números que también pueden enviar SMS. Valores: `true` · `false` * `limit`integer máx. 100 #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar los números de un perfil [Sección titulada «Listar los números de un perfil»](#listar-los-números-de-un-perfil) GET`/v1/phone-numbers` Los activos y los que están en revisión (los rechazados siguen 30 días, con el motivo). #### Parámetros * `profileId`string El perfil cuyos números listar; sin él, los de todos los perfiles. #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Comprar un número [Sección titulada «Comprar un número»](#comprar-un-número) POST`/v1/phone-numbers` Propietarios y admins. Hace falta al menos un mes del número en el saldo. Los países que regulan los números responden 202 `kyc_required`: envía la identidad del titular con POST /phone-numbers/kyc. #### Cuerpo * `profileId`stringobligatorio * `country`stringobligatorio * `numberType`string local, mobile, national o toll_free; si no se envía, el del país por defecto. Valores: `local` · `mobile` · `national` · `toll_free` * `phoneNumber`string Un número exacto de GET /v1/phone-numbers/available. No en países que piden KYC. * `areaCode`string Cualquier número de esta zona (sin phoneNumber). * `sms`boolean Elegir un número que pueda enviar SMS y activarlos. * `idempotencyKey`string Envía el mismo valor al reintentar, para que un reintento nunca compre un segundo número. máx. 100 #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/phone-numbers" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profileId": "prf_8f2k4d",
"country": "GB",
"numberType": "mobile",
"sms": true
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"profileId": "prf_8f2k4d",
"country": "GB",
"numberType": "mobile",
"sms": true
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/phone-numbers",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"profileId": "prf_8f2k4d",
"country": "GB",
"numberType": "mobile",
"sms": True
},
)
data = res.json()["data"]
```
## El formulario KYC de un país [Sección titulada «El formulario KYC de un país»](#el-formulario-kyc-de-un-país) GET`/v1/phone-numbers/kyc` Lo que la operadora necesita saber de quien tendrá el número: texto, fecha, dirección, documentos y, a veces, una verificación de identidad posterior (`action`). #### Parámetros * `country`stringobligatorio * `numberType`string local, mobile, national o toll_free; si no se envía, el del país por defecto. Valores: `local` · `mobile` · `national` · `toll_free` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/kyc?country=ES" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc?country=ES', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/kyc?country=ES",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Pedir un número con KYC [Sección titulada «Pedir un número con KYC»](#pedir-un-número-con-kyc) POST`/v1/phone-numbers/kyc` Pide el número de un país regulado con la identidad del titular. Espera la revisión de la operadora (`pending_regulatory`, normalmente de 1 a 3 días laborables) y solo se cobra cuando está activo. Si el formulario tenía verificación de identidad, el número tiene `regulatory.idVerificationUrl` para enviárselo al titular. #### Cuerpo * `profileId`stringobligatorio * `country`stringobligatorio * `numberType`string local, mobile, national o toll_free; si no se envía, el del país por defecto. Valores: `local` · `mobile` · `national` · `toll_free` * `values`object requirementId → valor, para los campos `text` y `date`. * `documents`object\[] máx. 20 elementos * `address`object * `endUserFirstName`string Nombre legal, cuando el formulario tiene verificación de identidad (`action`). máx. 100 * `endUserLastName`string máx. 100 * `areaCode`string * `phoneNumber`string * `sms`boolean * `preOrder`boolean Aceptar que la operadora consiga un número cuando la zona no tiene existencias (normalmente de 2 a 4 semanas). * `submissionId`string Envía el mismo valor al reintentar, para que un reintento nunca pida un segundo número. máx. 100 #### Respuesta 202 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/phone-numbers/kyc" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profileId": "prf_8f2k4d",
"country": "ES",
"values": {
"d7e8f9a0-…": "Acme SL"
},
"documents": [
{
"requirementId": "e8f9a0b1-…",
"documentId": "kdoc_…"
}
],
"address": {
"requirementId": "f9a0b1c2-…",
"countryCode": "ES",
"streetAddress": "Gran Vía 1",
"locality": "Madrid",
"postalCode": "28013"
}
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"profileId": "prf_8f2k4d",
"country": "ES",
"values": {
"d7e8f9a0-…": "Acme SL"
},
"documents": [
{
"requirementId": "e8f9a0b1-…",
"documentId": "kdoc_…"
}
],
"address": {
"requirementId": "f9a0b1c2-…",
"countryCode": "ES",
"streetAddress": "Gran Vía 1",
"locality": "Madrid",
"postalCode": "28013"
}
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/phone-numbers/kyc",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"profileId": "prf_8f2k4d",
"country": "ES",
"values": {
"d7e8f9a0-…": "Acme SL"
},
"documents": [
{
"requirementId": "e8f9a0b1-…",
"documentId": "kdoc_…"
}
],
"address": {
"requirementId": "f9a0b1c2-…",
"countryCode": "ES",
"streetAddress": "Gran Vía 1",
"locality": "Madrid",
"postalCode": "28013"
}
},
)
data = res.json()["data"]
```
## Subir un documento KYC [Sección titulada «Subir un documento KYC»](#subir-un-documento-kyc) POST`/v1/phone-numbers/kyc/documents` Un archivo (PDF, JPEG o PNG, hasta 4 MB, en base64). Va directo a la operadora; Marsial no guarda nada. Usa el id que devuelve en POST /phone-numbers/kyc. #### Cuerpo * `filename`stringobligatorio máx. 200 * `contentType`stringobligatorio Valores: `application/pdf` · `image/jpeg` · `image/png` * `data`stringobligatorio El archivo en base64, hasta 4 MB. Para un DNI, las dos caras en un solo archivo. máx. 6.000.000 #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/phone-numbers/kyc/documents" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "id.pdf",
"contentType": "application/pdf",
"data": "JVBERi0xLjQK…"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc/documents', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"filename": "id.pdf",
"contentType": "application/pdf",
"data": "JVBERi0xLjQK…"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/phone-numbers/kyc/documents",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"filename": "id.pdf",
"contentType": "application/pdf",
"data": "JVBERi0xLjQK…"
},
)
data = res.json()["data"]
```
## Ver un número [Sección titulada «Ver un número»](#ver-un-número) GET`/v1/phone-numbers/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/num_…" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/num_…",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Dar de baja un número [Sección titulada «Dar de baja un número»](#dar-de-baja-un-número) DELETE`/v1/phone-numbers/{id}` Propietarios y admins. Devuelve el número y deja de cobrarse; un número en revisión o un pedido se cancela. No se puede recuperar. #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/phone-numbers/num_…" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/phone-numbers/num_…', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/phone-numbers/num_…",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Configurar las llamadas entrantes [Sección titulada «Configurar las llamadas entrantes»](#configurar-las-llamadas-entrantes) PATCH`/v1/phone-numbers/{id}/calls` A dónde van las llamadas (un teléfono, una dirección SIP o un agente de voz por wss\://), buzón de voz, horario, llamadas bloqueadas, grabación y transcripción. Solo cambian los campos enviados. #### Parámetros * `id`stringobligatorio #### Cuerpo * `enabled`boolean false desactiva las llamadas en el número (los ajustes se guardan). * `forwardTo`string | "" A dónde van las llamadas entrantes: tel:+E164, sip:… o wss\://… (un agente de voz con IA). Vacío lo quita. * `voicemailEnabled`boolean * `voicemailGreeting`string máx. 500 * `recordingEnabled`boolean Graba las llamadas (antes suena un aviso). * `transcriptionEnabled`boolean * `transcriptionLanguage`string Valores: `auto` · `en` · `es` * `businessHoursEnabled`boolean * `businessHoursTimezone`string Zona horaria IANA, por ejemplo Europe/Madrid. máx. 60 * `businessHours`object\[] máx. 21 elementos * `blockedCallers`string\[] Sustituye la lista entera. máx. 500 elementos * `forwardCallerId`string Valores: `business` · `caller` #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/phone-numbers/num_…/calls" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"forwardTo": "tel:+34600111222",
"recordingEnabled": true
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/calls', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"forwardTo": "tel:+34600111222",
"recordingEnabled": true
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/phone-numbers/num_…/calls",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"forwardTo": "tel:+34600111222",
"recordingEnabled": True
},
)
data = res.json()["data"]
```
## Activar o desactivar los SMS [Sección titulada «Activar o desactivar los SMS»](#activar-o-desactivar-los-sms) PUT`/v1/phone-numbers/{id}/sms` Solo en números que pueden enviarlos. Los números de EE. UU. necesitan además un registro de operadora (10DLC) que Marsial aún no ofrece. #### Parámetros * `id`stringobligatorio #### Cuerpo * `enabled`booleanobligatorio #### Respuesta 200 * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/phone-numbers/num_…/sms" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/sms', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"enabled": true
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/phone-numbers/num_…/sms",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"enabled": True
},
)
data = res.json()["data"]
```
# Publicaciones
> Publica ahora, programa, usa la cola o guarda borradores en una o varias cuentas.
Publica ahora, programa, usa la cola o guarda borradores en una o varias cuentas. ## Crear una publicación [Sección titulada «Crear una publicación»](#crear-una-publicación) POST`/v1/posts` Se publica ahora salvo que envíes `scheduledFor`, `queue: true` o `draft: true`. Cada destino es una cuenta y puede llevar su propio texto, medios y opciones de red (`instagram`, `youtube`, `tiktok`…). Los destinos de TikTok siempre necesitan opciones `tiktok`. Un `scheduledFor` en el pasado se rechaza (omítelo para publicar ya). #### Cuerpo * `content`stringobligatorio Texto que se publica en los destinos que no llevan el suyo. máx. 10.000 * `media`object\[] Imágenes, vídeos o documentos. Súbelos antes con POST /v1/media/upload-url. máx. 35 elementos * `targets`object\[]obligatorio máx. 50 elementos * `scheduledFor`string (date-time) Cuándo publicar (ISO 8601 con zona). Sin él se publica ya. * `timezone`string Zona horaria IANA a la que se refiere scheduledFor. máx. 64 * `queue`boolean Tomar el siguiente hueco libre de la cola del perfil. * `draft`boolean Guardar sin publicar ni programar. * `requiresApproval`boolean La deja en `pending_approval` hasta que un propietario o admin la apruebe. Los miembros de un workspace que exige aprobación siempre pasan por aquí. #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Our autumn collection is here 🍂",
"media": [
{
"type": "image",
"url": "https://cdn.acme.com/autumn.jpg"
}
],
"targets": [
{
"accountId": "acc_3k9x2m"
},
{
"accountId": "acc_9z8y7x",
"youtube": {
"title": "Autumn collection"
}
}
],
"scheduledFor": "2026-10-30T09:00:00+01:00"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Our autumn collection is here 🍂",
"media": [
{
"type": "image",
"url": "https://cdn.acme.com/autumn.jpg"
}
],
"targets": [
{
"accountId": "acc_3k9x2m"
},
{
"accountId": "acc_9z8y7x",
"youtube": {
"title": "Autumn collection"
}
}
],
"scheduledFor": "2026-10-30T09:00:00+01:00"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"content": "Our autumn collection is here 🍂",
"media": [
{
"type": "image",
"url": "https://cdn.acme.com/autumn.jpg"
}
],
"targets": [
{
"accountId": "acc_3k9x2m"
},
{
"accountId": "acc_9z8y7x",
"youtube": {
"title": "Autumn collection"
}
}
],
"scheduledFor": "2026-10-30T09:00:00+01:00"
},
)
data = res.json()["data"]
```
## Listar publicaciones [Sección titulada «Listar publicaciones»](#listar-publicaciones) GET`/v1/posts` De la más reciente a la más antigua; opcionalmente de un perfil o un estado, por páginas. #### Parámetros * `limit`integer máx. 100 * `cursor`string El nextCursor de la página anterior. máx. 64 * `profileId`string Solo las publicaciones a cuentas de este perfil. * `status`string Valores: `draft` · `pending_approval` · `scheduled` · `paused` · `publishing` · `published` · `partial` · `failed` · `cancelled` · `removed` · `deleted` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/posts?limit=20" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts?limit=20', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/posts?limit=20",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Importar publicaciones desde un CSV [Sección titulada «Importar publicaciones desde un CSV»](#importar-publicaciones-desde-un-csv) POST`/v1/posts/import` Una publicación por fila, hasta 50 filas. Columnas: `content`, `accounts` (ids separados por `|`) o `group`, `schedule_time`, `timezone`, `queue`, `draft`, `media_urls` y las de cada red (mira la guía de importación). Envía antes `dryRun: true` para comprobar las filas sin publicar. #### Cuerpo * `csv`stringobligatorio El texto del CSV, con la fila de cabecera primero. máx. 1.000.000 * `dryRun`boolean Comprobar cada fila sin publicar. #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/import" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/import', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/import",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Cambiar una publicación que no ha salido [Sección titulada «Cambiar una publicación que no ha salido»](#cambiar-una-publicación-que-no-ha-salido) PATCH`/v1/posts/{id}` Borradores, programadas, con error y canceladas. Los campos que no envíes se mantienen; `targets` sustituye la lista entera. `draft: false` publica un borrador ahora, en `scheduledFor` o en la cola. #### Parámetros * `id`stringobligatorio #### Cuerpo * `content`string Texto que se publica en los destinos que no llevan el suyo. máx. 10.000 * `media`object\[] Imágenes, vídeos o documentos. Súbelos antes con POST /v1/media/upload-url. máx. 35 elementos * `targets`object\[] máx. 50 elementos * `scheduledFor`string (date-time) Cuándo publicar (ISO 8601 con zona). Sin él se publica ya. * `timezone`string Zona horaria IANA a la que se refiere scheduledFor. máx. 64 * `queue`boolean Tomar el siguiente hueco libre de la cola del perfil. * `draft`boolean Guardar sin publicar ni programar. * `requiresApproval`boolean La deja en `pending_approval` hasta que un propietario o admin la apruebe. Los miembros de un workspace que exige aprobación siempre pasan por aquí. #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Ver una publicación [Sección titulada «Ver una publicación»](#ver-una-publicación) GET`/v1/posts/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Borrar una publicación [Sección titulada «Borrar una publicación»](#borrar-una-publicación) DELETE`/v1/posts/{id}` La quita de Marsial y antes retira sus copias publicadas donde la red lo permite. Instagram y TikTok no lo permiten: borra esas copias en la app y envía `keepLive=true`. #### Parámetros * `id`stringobligatorio * `keepLive`string Elimina la publicación de Marsial aunque queden copias en redes que no dejan borrarlas (Instagram, TikTok): bórralas antes en la app. Valores: `true` · `false` #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Editar el texto de una publicación publicada [Sección titulada «Editar el texto de una publicación publicada»](#editar-el-texto-de-una-publicación-publicada) POST`/v1/posts/{id}/edit` En X (cuentas Premium, durante la primera hora), Facebook, LinkedIn, YouTube, Pinterest, Google Business, Telegram, Discord y Reddit. Las imágenes y vídeos no cambian. #### Parámetros * `id`stringobligatorio #### Cuerpo * `content`stringobligatorio El nuevo texto de la publicación. máx. 10.000 * `accountId`string Editar solo la copia de esta cuenta; si no, todas las publicadas. #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/edit" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/edit', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/edit",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Ver las métricas de una publicación [Sección titulada «Ver las métricas de una publicación»](#ver-las-métricas-de-una-publicación) GET`/v1/posts/{id}/metrics` Impresiones, alcance, reproducciones, me gusta, comentarios, compartidos, guardados y clics, en total y por cuenta. Cada red da las suyas. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/posts/pst_7q1w0e/metrics" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/metrics', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/metrics",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Cancelar una publicación programada, un borrador o una pendiente de aprobación [Sección titulada «Cancelar una publicación programada, un borrador o una pendiente de aprobación»](#cancelar-una-publicación-programada-un-borrador-o-una-pendiente-de-aprobación) POST`/v1/posts/{id}/cancel` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/cancel" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/cancel', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/cancel",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Aprobar o rechazar una publicación [Sección titulada «Aprobar o rechazar una publicación»](#aprobar-o-rechazar-una-publicación) POST`/v1/posts/{id}/review` Solo para publicaciones en `pending_approval`, por propietarios, admins o una API key. Aprobar la programa para su fecha, la mete en la cola si la pidió o la publica ya si su fecha pasó. Rechazar la devuelve a borrador con la nota y envía `post.rejected`. #### Parámetros * `id`stringobligatorio #### Cuerpo * `decision`stringobligatorio `approve` la programa (o la publica ya si su fecha pasó); `reject` la devuelve a borrador. Valores: `approve` · `reject` * `note`string El motivo, para quien la escribió. Se muestra con el borrador tras un rechazo. máx. 1000 #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/review" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/review",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Reciclar una publicación [Sección titulada «Reciclar una publicación»](#reciclar-una-publicación) PUT`/v1/posts/{id}/recycling` La vuelve a publicar cada `every` semanas o meses como una publicación nueva (`recycledFrom` apunta a la original), hasta `maxCopies` o `until`. Las copias no van a YouTube ni a TikTok, y cada cuenta puede tener hasta 10 publicaciones reciclándose. Enviarlo otra vez cambia la regla y mantiene la cuenta de copias. #### Parámetros * `id`stringobligatorio #### Cuerpo * `every`integerobligatorio Cuántas unidades entre copia y copia. máx. 52 * `unit`stringobligatorio `week` (semana) o `month` (mes). Valores: `week` · `month` * `startAt`string (date-time) Cuándo sale la primera copia. Por defecto, un intervalo después de la fecha de la publicación; si es antigua, la siguiente fecha de esa serie, a la misma hora. * `maxCopies`integer Parar tras este número de copias. máx. 100 * `until`string (date-time) Parar después de esta fecha. * `variations`string\[] Textos que se usan por turnos en lugar del de la publicación. El texto propio de un destino sigue mandando. Recomendado en X y Pinterest, que penalizan las repeticiones. mín. 2máx. 20 elementos * `timezone`string Zona horaria IANA (por ejemplo `Europe/Madrid`) en la que se cuenta el intervalo, para que las copias mantengan su hora local cuando cambia la hora. UTC por defecto. máx. 64 #### Respuesta 200 * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Dejar de reciclar una publicación [Sección titulada «Dejar de reciclar una publicación»](#dejar-de-reciclar-una-publicación) DELETE`/v1/posts/{id}/recycling` Las copias ya creadas se quedan como están. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Reintentar los destinos fallidos [Sección titulada «Reintentar los destinos fallidos»](#reintentar-los-destinos-fallidos) POST`/v1/posts/{id}/retry` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/retry" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/retry', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/retry",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Retirar una publicación [Sección titulada «Retirar una publicación»](#retirar-una-publicación) POST`/v1/posts/{id}/unpublish` De todas las redes o solo de `accountId`. #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`string #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/posts/pst_7q1w0e/unpublish" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/posts/pst_7q1w0e/unpublish', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/posts/pst_7q1w0e/unpublish",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"accountId": "acc_3k9x2m"
},
)
data = res.json()["data"]
```
# Perfiles
> Un perfil es una marca o un cliente final. Las cuentas sociales se conectan a un perfil.
Un perfil es una marca o un cliente final. Las cuentas sociales se conectan a un perfil. ## Listar perfiles [Sección titulada «Listar perfiles»](#listar-perfiles) GET`/v1/profiles` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/profiles" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/profiles', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/profiles",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Crear un perfil [Sección titulada «Crear un perfil»](#crear-un-perfil) POST`/v1/profiles` #### Cuerpo * `name`stringobligatorio Nombre de la marca o del cliente final. máx. 100 * `timezone`string Zona horaria IANA, por ejemplo Europe/Madrid. La usa la cola. máx. 64 * `externalId`string Tu propio id para este cliente; se devuelve tal cual. máx. 200 #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/profiles" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme",
"timezone": "Europe/Madrid",
"externalId": "customer-42"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/profiles', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Acme",
"timezone": "Europe/Madrid",
"externalId": "customer-42"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/profiles",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"name": "Acme",
"timezone": "Europe/Madrid",
"externalId": "customer-42"
},
)
data = res.json()["data"]
```
## Ver un perfil [Sección titulada «Ver un perfil»](#ver-un-perfil) GET`/v1/profiles/{id}` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/profiles/prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Editar un perfil [Sección titulada «Editar un perfil»](#editar-un-perfil) PATCH`/v1/profiles/{id}` #### Parámetros * `id`stringobligatorio #### Cuerpo * `name`string Nombre de la marca o del cliente final. máx. 100 * `timezone`string Zona horaria IANA, por ejemplo Europe/Madrid. La usa la cola. máx. 64 * `externalId`string Tu propio id para este cliente; se devuelve tal cual. máx. 200 #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Spain"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/profiles/prf_8f2k4d', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Acme Spain"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"name": "Acme Spain"
},
)
data = res.json()["data"]
```
## Borrar un perfil [Sección titulada «Borrar un perfil»](#borrar-un-perfil) DELETE`/v1/profiles/{id}` También desconecta sus cuentas. #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/profiles/prf_8f2k4d', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
# Cola
> Huecos semanales por perfil. Los posts con queue: true toman el siguiente libre.
Huecos semanales por perfil. Los posts con `queue: true` toman el siguiente libre. ## Ver la cola de un perfil [Sección titulada «Ver la cola de un perfil»](#ver-la-cola-de-un-perfil) GET`/v1/profiles/{id}/queue` #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Definir los huecos de la cola [Sección titulada «Definir los huecos de la cola»](#definir-los-huecos-de-la-cola) PUT`/v1/profiles/{id}/queue` Sustituye todos los huecos. Los días van de 0 (domingo) a 6 (sábado); las horas, HH:mm en la zona horaria de la cola. #### Parámetros * `id`stringobligatorio #### Cuerpo * `timezone`string máx. 64 * `slots`object\[]obligatorio máx. 100 elementos #### Respuesta 200 * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 4,
"time": "18:00"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 4,
"time": "18:00"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 4,
"time": "18:00"
}
]
},
)
data = res.json()["data"]
```
## Borrar la cola [Sección titulada «Borrar la cola»](#borrar-la-cola) DELETE`/v1/profiles/{id}/queue` #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
# SMS
> Envía SMS y MMS desde tus números. Las respuestas llegan a la bandeja (plataforma sms) y como eventos message.received.
Envía SMS y MMS desde tus números. Las respuestas llegan a la bandeja (plataforma `sms`) y como eventos `message.received`. ## Quién respondió STOP [Sección titulada «Quién respondió STOP»](#quién-respondió-stop) GET`/v1/phone-numbers/{id}/sms/opt-outs` Los SMS desde este número a ellos se rechazan. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/phone-numbers/num_…/sms/opt-outs" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/sms/opt-outs', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/phone-numbers/num_…/sms/opt-outs",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Enviar un SMS [Sección titulada «Enviar un SMS»](#enviar-un-sms) POST`/v1/sms/messages` Desde uno de tus números con SMS activados. Las respuestas llegan a la conversación de la bandeja que devuelve. #### Cuerpo * `numberId`stringobligatorio El número que lo envía (num\_…), con SMS activados. * `to`stringobligatorio * `text`string Hasta 10 segmentos de SMS. máx. 1530 * `mediaUrls`string (uri)\[] URL públicas de archivos: envía un MMS donde la operadora lo permite. máx. 10 elementos * `sendAt`string (date-time) Programarlo para más tarde. * `idempotencyKey`string máx. 100 #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/sms/messages" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"numberId": "num_…",
"to": "+447700900123",
"text": "Your order 4821 is on its way"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/sms/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"numberId": "num_…",
"to": "+447700900123",
"text": "Your order 4821 is on its way"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/sms/messages",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"numberId": "num_…",
"to": "+447700900123",
"text": "Your order 4821 is on its way"
},
)
data = res.json()["data"]
```
# Equipo
> Miembros e invitaciones. Propietarios y admins gestionan el equipo; los miembros publican y responden.
Miembros e invitaciones. Propietarios y admins gestionan el equipo; los miembros publican y responden. ## Ver miembros e invitaciones [Sección titulada «Ver miembros e invitaciones»](#ver-miembros-e-invitaciones) GET`/v1/team` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/team" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/team', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/team",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Invitar a alguien [Sección titulada «Invitar a alguien»](#invitar-a-alguien) POST`/v1/team/invitations`Solo desde el panel Devuelve un enlace para enviarle. Se une al entrar con el email invitado. #### Cuerpo * `email`string (email)obligatorio A quién invitas; tendrá que entrar con este email para aceptar. * `role`string `admin` gestiona el equipo, las API keys y los webhooks; `member` publica y responde. Valores: `admin` · `member`Por defecto: `"member"` #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/team/invitations" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/team/invitations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/team/invitations",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Cancelar una invitación [Sección titulada «Cancelar una invitación»](#cancelar-una-invitación) DELETE`/v1/team/invitations/{id}`Solo desde el panel #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/team/invitations/inv_9n1m4l" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/team/invitations/inv_9n1m4l', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/team/invitations/inv_9n1m4l",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Cambiar un rol [Sección titulada «Cambiar un rol»](#cambiar-un-rol) PATCH`/v1/team/members/{userId}`Solo desde el panel #### Parámetros * `userId`stringobligatorio #### Cuerpo * `role`stringobligatorio Valores: `admin` · `member` #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/team/members/{userId}" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/team/members/{userId}', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/team/members/{userId}",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Quitar a alguien, o salir [Sección titulada «Quitar a alguien, o salir»](#quitar-a-alguien-o-salir) DELETE`/v1/team/members/{userId}`Solo desde el panel #### Parámetros * `userId`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/team/members/{userId}" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/team/members/{userId}', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/team/members/{userId}",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Aceptar una invitación [Sección titulada «Aceptar una invitación»](#aceptar-una-invitación) POST`/v1/invitations/accept`Solo desde el panel #### Cuerpo * `token`stringobligatorio El token del enlace de invitación. mín. 16máx. 200 #### Respuesta 200 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/invitations/accept" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/invitations/accept', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/invitations/accept",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
# Webhooks
> Recibe los eventos de Marsial en tu endpoint HTTPS.
Recibe los eventos de Marsial en tu endpoint HTTPS. ## Ver el endpoint de webhooks [Sección titulada «Ver el endpoint de webhooks»](#ver-el-endpoint-de-webhooks) GET`/v1/webhook-endpoint` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/webhook-endpoint" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/webhook-endpoint', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Configurar el endpoint de webhooks [Sección titulada «Configurar el endpoint de webhooks»](#configurar-el-endpoint-de-webhooks) PUT`/v1/webhook-endpoint` Sin `events` recibes todos. El secreto de firma solo se devuelve la primera vez. #### Cuerpo * `url`string (starts_with)obligatorio * `events`string\[] #### Respuesta 200 * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/webhook-endpoint" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.acme.com/webhooks/marsial"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/webhook-endpoint', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"url": "https://app.acme.com/webhooks/marsial"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"url": "https://app.acme.com/webhooks/marsial"
},
)
data = res.json()["data"]
```
## Borrar el endpoint de webhooks [Sección titulada «Borrar el endpoint de webhooks»](#borrar-el-endpoint-de-webhooks) DELETE`/v1/webhook-endpoint` #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/webhook-endpoint" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/webhook-endpoint', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Enviar un evento de prueba [Sección titulada «Enviar un evento de prueba»](#enviar-un-evento-de-prueba) POST`/v1/webhook-endpoint/test` Envía al endpoint un ejemplo del evento con `test: true` e ids inventados, firmado y con reintentos como uno real. El endpoint tiene que estar suscrito a él. #### Cuerpo * `type`stringobligatorio El evento del que enviar un ejemplo. #### Respuesta 202 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/webhook-endpoint/test" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/webhook-endpoint/test', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/webhook-endpoint/test",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
# WhatsApp
> Números de WhatsApp Business: plantillas que revisa Meta, escribir primero con una plantilla aprobada (POST /inbox/conversations) y difusiones a muchos números. Las respuestas dentro de las 24 horas van por la bandeja. Estas cuentas no publican.
Números de WhatsApp Business: plantillas que revisa Meta, escribir primero con una plantilla aprobada (POST /inbox/conversations) y difusiones a muchos números. Las respuestas dentro de las 24 horas van por la bandeja. Estas cuentas no publican. ## Listar plantillas [Sección titulada «Listar plantillas»](#listar-plantillas) GET`/v1/accounts/{id}/whatsapp/templates` Se leen en directo de Meta, una por nombre e idioma. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Crear una plantilla [Sección titulada «Crear una plantilla»](#crear-una-plantilla) POST`/v1/accounts/{id}/whatsapp/templates` Meta la revisa (hasta 24 horas): empieza como PENDING y solo se puede enviar cuando está APPROVED. La categoría decide lo que cobra Meta por cada mensaje. #### Parámetros * `id`stringobligatorio #### Cuerpo * `name`stringobligatorio * `category`stringobligatorio Valores: `MARKETING` · `UTILITY` · `AUTHENTICATION` * `language`stringobligatorio Código de idioma de Meta, por ejemplo es, en_US, pt_BR. mín. 2máx. 10 * `components`object\[]obligatorio Los componentes de Meta: un BODY con su texto ({{1}}, {{2}}…) y un ejemplo de cada dato, y si quieres HEADER, FOOTER y BUTTONS. máx. 10 elementos #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Borrar una plantilla [Sección titulada «Borrar una plantilla»](#borrar-una-plantilla) DELETE`/v1/accounts/{id}/whatsapp/templates/{name}` Todos los idiomas del nombre, o solo `language`. #### Parámetros * `id`stringobligatorio * `name`stringobligatorio * `language`string mín. 2máx. 10 #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates/pedido_listo" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates/pedido_listo', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/templates/pedido_listo",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
```
## Escribir primero con una plantilla [Sección titulada «Escribir primero con una plantilla»](#escribir-primero-con-una-plantilla) POST`/v1/inbox/conversations` Abre una conversación de WhatsApp (o la retoma tras 24 horas sin mensajes) con una plantilla APPROVED. La respuesta llega a la bandeja y como `message.received`; desde ahí responde con POST /inbox/conversations/{id}/messages durante 24 horas. #### Cuerpo * `accountId`stringobligatorio La cuenta de WhatsApp desde la que escribir. * `phone`stringobligatorio A quién escribir. * `template`objectobligatorio Una plantilla APPROVED: la única forma de escribir primero, o tras 24 horas sin mensajes. #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/inbox/conversations" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/inbox/conversations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/inbox/conversations",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Listar difusiones [Sección titulada «Listar difusiones»](#listar-difusiones) GET`/v1/accounts/{id}/whatsapp/broadcasts` Con cuántos destinatarios recibieron, leyeron o fallaron. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Enviar o programar una difusión [Sección titulada «Enviar o programar una difusión»](#enviar-o-programar-una-difusión) POST`/v1/accounts/{id}/whatsapp/broadcasts` Una plantilla APPROVED a una lista de números, ahora o en `scheduledFor`. Cada destinatario es un mensaje enviado; Meta cobra su tarifa de plantilla a tu cuenta de WhatsApp Business. Un número nuevo llega como mucho a 250 personas al día hasta que Meta amplía su límite. #### Parámetros * `id`stringobligatorio #### Cuerpo * `name`stringobligatorio máx. 200 * `template`objectobligatorio * `phones`string\[]obligatorio Los destinatarios con su prefijo de país. máx. 10.000 elementos * `scheduledFor`string (date-time) Se envía a esta hora; si no, ahora. #### Respuesta 201 * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Cancelar una difusión [Sección titulada «Cancelar una difusión»](#cancelar-una-difusión) POST`/v1/accounts/{id}/whatsapp/broadcasts/{broadcastId}/cancel` Una programada, o lo que queda de una que se está enviando. Lo ya enviado, enviado está. #### Parámetros * `id`stringobligatorio * `broadcastId`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X POST "https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts/bcs_…/cancel" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts/bcs_…/cancel', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.marsial.dev/v1/accounts/acc_3k9x2m/whatsapp/broadcasts/bcs_…/cancel",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
# Workspace
> Tu workspace y quién está llamando.
Tu workspace y quién está llamando. ## Quién llama [Sección titulada «Quién llama»](#quién-llama) GET`/v1/me` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/me" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/me', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/me",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Ver el workspace [Sección titulada «Ver el workspace»](#ver-el-workspace) GET`/v1/workspace` #### Respuesta 200 * curl
```bash
curl "https://api.marsial.dev/v1/workspace" \
-H "Authorization: Bearer $MARSIAL_API_KEY"
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/workspace', {
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.marsial.dev/v1/workspace",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
)
data = res.json()["data"]
```
## Editar el workspace [Sección titulada «Editar el workspace»](#editar-el-workspace) PATCH`/v1/workspace`Solo desde el panel #### Cuerpo * `name`string máx. 100 * `usage`string Valores: `api` · `self` * `requireApproval`boolean Las publicaciones de los miembros esperan a que un propietario o admin las apruebe. * `requireAdsApproval`boolean Los cambios de anuncios que gastan dinero pedidos por miembros y agentes de IA esperan a que un propietario o admin los apruebe. #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.marsial.dev/v1/workspace" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"usage": "api"
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/workspace', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"usage": "api"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.marsial.dev/v1/workspace",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"usage": "api"
},
)
data = res.json()["data"]
```
# Webhooks
> Recibe eventos firmados cuando se publica, falla o se desconecta una cuenta.
## Configura tu endpoint [Sección titulada «Configura tu endpoint»](#configura-tu-endpoint) Una URL HTTPS por workspace. Sin `events` recibes todos. El secreto de firma solo se devuelve al crearlo: guárdalo. * curl
```bash
curl -X PUT "https://api.marsial.dev/v1/webhook-endpoint" \
-H "Authorization: Bearer $MARSIAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.acme.com/webhooks/marsial",
"events": [
"post.published",
"post.failed",
"account.disconnected"
]
}'
```
* Node
```js
const res = await fetch('https://api.marsial.dev/v1/webhook-endpoint', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"url": "https://app.acme.com/webhooks/marsial",
"events": [
"post.published",
"post.failed",
"account.disconnected"
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.marsial.dev/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},
json={
"url": "https://app.acme.com/webhooks/marsial",
"events": [
"post.published",
"post.failed",
"account.disconnected"
]
},
)
data = res.json()["data"]
```
## Eventos [Sección titulada «Eventos»](#eventos) | Evento | Cuándo | `data` | | ---------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | `post.scheduled` | Se programó o entró en la cola | `post` | | `post.published` | Salió en todas las redes | `post` | | `post.partial` | Salió en algunas y falló en otras | `post` | | `post.failed` | No salió en ninguna, también cuando falla una red sola (una imagen que no descarga) | `post` | | `post.cancelled` | Se canceló | `post` | | `post.removed` | Se retiró de una red (también al borrarla con copias publicadas, antes de `post.deleted`) | `post` | | `post.rejected` | Se rechazó en la revisión y volvió a borrador | `post` | | `post.recycled` | Se creó una copia reciclada | `post` (la copia), `recycledFrom` | | `post.draft_saved` | Se guardó como borrador | `post` | | `post.deleted` | Se eliminó de Marsial | `post` con `status: "deleted"`; cada destino conserva el suyo (una copia que sigue en Instagram o TikTok, `published`) | | `account.connected` | Se conectó una cuenta | `account` | | `account.disconnected` | Se desconectó o hay que reconectarla | `account` | | `message.received` | Alguien escribió un mensaje directo | `accountId`, `conversationId`, `message` | | `comment.received` | Alguien comentó una publicación | `accountId`, `postId`, `comment` | | `review.received` | Llegó una reseña nueva (Google Business) | `accountId`, `review` | Para probar tu endpoint sin esperar a un evento real, `POST /v1/webhook-endpoint/test` con `{ "type": "post.failed" }` (o cualquier otro tipo al que esté suscrito) envía un ejemplo firmado con `test: true` e ids inventados. Cada estado de una publicación se avisa una vez: Marsial manda `post.scheduled` o `post.published` en cuanto lo sabe, aunque la red no diga nada, y no lo repite. Las entregas pueden cruzarse: ordénalas por `createdAt` (al borrar, `post.deleted` va un milisegundo después de `post.removed`). Cuerpo
```json
{
"id": "evt_9a8s7d",
"type": "post.published",
"createdAt": "2026-10-23T10:00:05.000Z",
"data": {
"post": {
"id": "pst_7q1w0e",
"status": "published",
"targets": [
{ "accountId": "acc_3k9x2m", "platform": "instagram", "status": "published", "url": "https://www.instagram.com/p/…" }
]
}
}
}
```
## Verifica la firma [Sección titulada «Verifica la firma»](#verifica-la-firma) Cada envío lleva `Marsial-Event`, `Marsial-Event-Id` y `Marsial-Signature: t=,v1=`. `v1` es el HMAC-SHA256 de `.` con tu secreto. Compáralo con el cuerpo sin parsear y rechaza firmas de hace más de 5 minutos. Node
```js
import { createHmac, timingSafeEqual } from 'node:crypto';
export const verifyMarsialSignature = (rawBody, header, secret) => {
const { t, v1 } = Object.fromEntries(header.split(',').map((part) => part.split('=')));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
};
```
Python
```python
import hmac, hashlib, time
def verify_marsial_signature(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(part.split("=", 1) for part in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
```
## Reintentos [Sección titulada «Reintentos»](#reintentos) * Responde con un `2xx` en menos de 10 segundos. Haz el trabajo pesado después. * Si fallas, reintentamos varias veces con espera creciente. * Un mismo evento puede llegar más de una vez: usa `Marsial-Event-Id` para no procesarlo dos veces.