This is the abridged developer documentation for Crier
# Construye con la API de Crier
> 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.usecrier.com](https://app.usecrier.com). 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.
# Para agentes de IA
> La documentación en texto plano para tu agente, tu asistente de código o tu editor.
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.usecrier.com/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 Crier con claves API.
Todas las peticiones a `/v1` llevan tu clave API en la cabecera `Authorization`:
```http
Authorization: Bearer crier_live_…
```
## Crear y revocar keys [Sección titulada «Crear y revocar keys»](#crear-y-revocar-keys) * Créalas en el [panel](https://app.usecrier.com), 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.usecrier.com/v1/me" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/me', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/me",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]
```
# Saldo y facturación
> Cómo se cobra Crier (prepago), qué cuesta cada cuenta y qué pasa cuando se acaba el saldo.
Crier 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. ## Qué se cobra [Sección titulada «Qué se cobra»](#qué-se-cobra) **Las cuentas conectadas**, día a día y por tramos. Las dos primeras son gratis para siempre: | Cuentas | Precio por cuenta y mes | | ------------ | ----------------------- | | 1 a 2 | Gratis | | 3 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 2 × 6 € = 12 € al mes, unos 0,39 € al día. Los impuestos van aparte. **El uso**, aparte: llamadas a la API de X y mensajes por encima de los incluidos, a las tarifas de [usecrier.com/precios](https://usecrier.com/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. ## Cuando se acaba [Sección titulada «Cuando se acaba»](#cuando-se-acaba) Con el saldo a cero, las dos primeras cuentas siguen funcionando (salvo las de X). Las demás y las de X 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 al conectar una tercera cuenta sin saldo: 402 Payment Required
```json
{
"error": {
"code": "payment_required",
"message": "Your balance is used up: add balance in Billing to use acc_9z8y7x. The first 2 accounts (except X) keep working."
}
}
```
# Novedades
> Lo nuevo en la API y el panel de Crier.
## 25 de octubre de 2026 [Sección titulada «25 de octubre de 2026»](#25-de-octubre-de-2026) * **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.usecrier.com, 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**: Crier 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 Crier 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). | | `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. | 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 Crier 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 Crier, en el panel y en la API.
| Término | En la API | Qué es | | ------------------ | ---------------------------- | -------------------------------------------------------------------------- | | Espacio de trabajo | `workspace` | Tu cuenta de Crier: 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 Crier envía a tu servidor cuando pasa algo. |
# 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.usecrier.com/v1/analytics/followers?profileId=prf_8f2k4d&from=2026-10-01" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/analytics/followers?profileId=prf_8f2k4d&from=2026-10-01', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/followers?profileId=prf_8f2k4d&from=2026-10-01",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/analytics/daily?profileId=prf_8f2k4d&accountId=acc_3k9x2m" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/analytics/daily?profileId=prf_8f2k4d&accountId=acc_3k9x2m', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/daily?profileId=prf_8f2k4d&accountId=acc_3k9x2m",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/analytics/best-times?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/analytics/best-times?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/best-times?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/analytics/top-posts?profileId=prf_8f2k4d&limit=10" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/analytics/top-posts?profileId=prf_8f2k4d&limit=10', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/top-posts?profileId=prf_8f2k4d&limit=10",
headers={"Authorization": f"Bearer {os.environ['CRIER_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 Crier si salió desde Crier; `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.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/review" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/review",
headers={"Authorization": f"Bearer {os.environ['CRIER_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
> Responde automáticamente en público a quien comente una palabra clave.
Una automatización vigila los comentarios de una cuenta y, cuando alguien escribe una palabra clave, le contesta en público por ti. Funciona en Instagram, Facebook, TikTok, Threads, LinkedIn y YouTube. ## Crear una [Sección titulada «Crear una»](#crear-una) * curl
```bash
curl -X POST "https://api.usecrier.com/v1/automations" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"name": "Enlace de precios",
"keywords": [
"precio",
"info"
],
"matchMode": "word",
"commentReply": "¡Hola! Tienes los precios en acme.com/precios"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/automations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m",
"name": "Enlace de precios",
"keywords": [
"precio",
"info"
],
"matchMode": "word",
"commentReply": "¡Hola! Tienes los precios en acme.com/precios"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/automations",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"accountId": "acc_3k9x2m",
"name": "Enlace de precios",
"keywords": [
"precio",
"info"
],
"matchMode": "word",
"commentReply": "¡Hola! Tienes los precios en acme.com/precios"
},
)
data = res.json()["data"]
```
- **`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 Crier. Para una publicada fuera de Crier, `inboxPostId` (el id de la [bandeja](/guides/inbox/)). Sin ninguno, vigila todas. - **`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 cuenta cuántas veces se activó en `stats`, y su historial dice qué comentario la activó y si la respuesta salió: * curl
```bash
curl "https://api.usecrier.com/v1/automations/aut_6r3e9w/logs" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/automations/aut_6r3e9w/logs', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/automations/aut_6r3e9w/logs",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]
```
Para pausarla, `PATCH` con `active: false`; para borrarla, `DELETE`.
# 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. Crier le devuelve a tu `redirectUrl` con el resultado en la query. * curl
```bash
curl "https://api.usecrier.com/v1/connect/linkedin?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/connect/linkedin?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/connect/linkedin?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado",
headers={"Authorization": f"Bearer {os.environ['CRIER_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` | | 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 | ### Lista las opciones [Sección titulada «Lista las opciones»](#lista-las-opciones) * curl
```bash
curl "https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/connect/sessions/cs_5t2y8u/select" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"optionId": "1042…"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/select', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/connect/sessions/cs_5t2y8u/select",
headers={"Authorization": f"Bearer {os.environ['CRIER_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`, `telegram`, `discord` y `snapchat`. ## Listar y vigilar cuentas [Sección titulada «Listar y vigilar cuentas»](#listar-y-vigilar-cuentas) * curl
```bash
curl "https://api.usecrier.com/v1/accounts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/accounts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/accounts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/import" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"csv": "content,accounts\nHola,acc_ig",
"dryRun": true
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/import', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts/import",
headers={"Authorization": f"Bearer {os.environ['CRIER_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: comentarios y menciones
> Lee y responde los comentarios de tus publicaciones y a quien menciona tus cuentas.
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_…`) son opacos: 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 Crier: * curl
```bash
curl "https://api.usecrier.com/v1/inbox/posts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/posts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/posts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/posts/thr_…/comments?accountId=acc_3k9x2m" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/posts/thr_…/comments?accountId=acc_3k9x2m', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/posts/thr_…/comments?accountId=acc_3k9x2m",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/posts/thr_…/comments" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"text": "¡Gracias, Luis!",
"commentId": "cmt_…"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/posts/thr_…/comments', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/inbox/posts/thr_…/comments",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/mentions?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
- Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/mentions?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
- Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/mentions?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/mentions/mtn_…/reply" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/inbox/mentions/mtn_…/reply', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/inbox/mentions/mtn_…/reply",
headers={"Authorization": f"Bearer {os.environ['CRIER_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. ## Pronto: mensajes directos y reseñas [Sección titulada «Pronto: mensajes directos y reseñas»](#pronto-mensajes-directos-y-reseñas) Los mensajes directos (`/inbox/conversations`) y las reseñas de Google Business y Facebook (`/inbox/reviews`) aparecen en la [referencia](/reference/inbox/) marcados como **Pronto**: todavía no se ofrecen.
# 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 Crier 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.usecrier.com/v1/media/upload-url" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "chaqueta.mp4",
"contentType": "video/mp4",
"size": 48211234
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/media/upload-url', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/media/upload-url",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.
# 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.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_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. | | `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, o retirada de todas las redes. | ## 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.usecrier.com/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts/pst_7q1w0e', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/edit" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Texto corregido"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/edit', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/edit",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/review" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "reject",
"note": "Cambia la foto de portada"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/review",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/recycling', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/account-groups" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/account-groups', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/account-groups",
headers={"Authorization": f"Bearer {os.environ['CRIER_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 Crier. Si sigue publicada, retírala antes.
# 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.usecrier.com/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d/queue', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['CRIER_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 Crier 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.usecrier.com/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/recycling', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/team" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/team', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/team",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.
# Introducción
> Qué es Crier, cómo se organiza y qué redes cubre.
Crier es una API y un panel para publicar en redes sociales. Conectas las cuentas de una marca (o las de tus clientes) una vez, con OAuth, y desde ahí publicas, programas, respondes comentarios 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.usecrier.com/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.usecrier.com/openapi.json), para generar clientes o importarlo en Postman. ## Redes [Sección titulada «Redes»](#redes) | Red | Qué publica | Comentarios | Menciones | | --------------- | ----------------------------------- | ----------- | ------------------------- | | Instagram | Feed, reels, historias y carruseles | Sí | Sí, y se pueden responder | | Facebook | Páginas: feed, reels e historias | 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í | — | | Threads | Posts e hilos | Sí | — | | Pinterest | Pines | — | — | | Google Business | Publicaciones de la ficha | — | — | 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 Crier 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.usecrier.com), ve a **Desarrolladores → Claves API** y crea una. Se muestra una sola vez: guárdala como variable de entorno.
```bash
export CRIER_API_KEY="crier_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.usecrier.com/v1/profiles" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme",
"timezone": "Europe/Madrid"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/profiles', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/profiles",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconectado",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "¡Hola desde Crier! 👋",
"targets": [
{
"accountId": "acc_3k9x2m"
}
]
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "¡Hola desde Crier! 👋",
"targets": [
{
"accountId": "acc_3k9x2m"
}
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"content": "¡Hola desde Crier! 👋",
"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 Crier, generado del documento OpenAPI. Base URL:
Cada endpoint de la API de Crier, generado del documento OpenAPI. Base URL: `https://api.usecrier.com/v1` · [Documento OpenAPI (JSON)](https://api.usecrier.com/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 Crier 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: manda al usuario a la URL y Crier lo devuelve a tu redirectUrl. (3 endpoints) [Cuentas](/reference/accounts/)Cuentas sociales conectadas, si pueden publicar, y sus tableros, listas y subreddits. (4 endpoints) [Grupos de cuentas](/reference/account-groups/)Selecciones de cuentas guardadas, para publicar en todas a la vez. (4 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) [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 Crier en tu endpoint HTTPS. (3 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/)Un saldo prepago: las cuentas conectadas a partir de las gratis se cobran día a día y el uso (API de X, mensajes) 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)
# 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.usecrier.com/v1/account-groups" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/account-groups', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/account-groups",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/account-groups" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/account-groups', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/account-groups",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/account-groups/grp_4h7j1k" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/account-groups/grp_4h7j1k', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/account-groups/grp_4h7j1k",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/account-groups/grp_4h7j1k" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/account-groups/grp_4h7j1k', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/account-groups/grp_4h7j1k",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/accounts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/accounts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/accounts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]
```
## 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.usecrier.com/v1/accounts/health?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/accounts/health?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/accounts/health?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/accounts/acc_3k9x2m/{kind}" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/accounts/acc_3k9x2m/{kind}', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/accounts/acc_3k9x2m/{kind}",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/accounts/acc_3k9x2m" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/accounts/acc_3k9x2m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/accounts/acc_3k9x2m",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/analytics/followers" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/analytics/followers', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/followers",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/analytics/daily" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/analytics/daily', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/daily",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/analytics/best-times" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/analytics/best-times', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/best-times",
headers={"Authorization": f"Bearer {os.environ['CRIER_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 Crier. #### 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.usecrier.com/v1/analytics/top-posts" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/analytics/top-posts', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/top-posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/api-keys" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/api-keys', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/api-keys",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/api-keys" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "production"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/api-keys', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/api-keys",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/api-keys/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/api-keys/key_2b4n6m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/api-keys/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/automations" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/automations', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/automations",
headers={"Authorization": f"Bearer {os.environ['CRIER_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 Crier 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.usecrier.com/v1/automations" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/automations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/automations",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/automations/aut_6r3e9w" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/automations/aut_6r3e9w', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/automations/aut_6r3e9w",
headers={"Authorization": f"Bearer {os.environ['CRIER_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 Crier 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.usecrier.com/v1/automations/aut_6r3e9w" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/automations/aut_6r3e9w', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/automations/aut_6r3e9w",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/automations/aut_6r3e9w" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/automations/aut_6r3e9w', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/automations/aut_6r3e9w",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/automations/aut_6r3e9w/logs" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/automations/aut_6r3e9w/logs', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/automations/aut_6r3e9w/logs",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]
```
# Facturación
> Un saldo prepago: las cuentas conectadas a partir de las gratis se cobran día a día y el uso (API de X, mensajes) según se produce. Se recarga desde el panel.
Un saldo prepago: las cuentas conectadas a partir de las gratis se cobran día a día y el uso (API de X, mensajes) 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, cuentas conectadas y lo que cuestan. Con el saldo agotado, conectar más allá de las cuentas gratis, y publicar o enviar desde las cuentas a partir de ellas o de X, responden 402. #### Respuesta 200 * curl
```bash
curl "https://api.usecrier.com/v1/billing" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/billing', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/billing",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/billing/movements" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/billing/movements', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/billing/movements",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/billing/top-up" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/billing/top-up', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/billing/top-up",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/billing/auto-recharge" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/billing/auto-recharge', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.usecrier.com/v1/billing/auto-recharge",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/billing/portal" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/billing/portal', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/billing/portal",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]
```
# Conexión
> Conecta una cuenta social: manda al usuario a la URL y Crier lo devuelve a tu redirectUrl.
Conecta una cuenta social: manda al usuario a la URL y Crier 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, Crier 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). #### 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. #### Respuesta 200 * curl
```bash
curl "https://api.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
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 Crier añadió a tu redirectUrl. Las sesiones caducan a la hora. #### Parámetros * `id`stringobligatorio #### Respuesta 200 * curl
```bash
curl "https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/connect/sessions/cs_5t2y8u/select" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"optionId": "1042…"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/select', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/connect/sessions/cs_5t2y8u/select",
headers={"Authorization": f"Bearer {os.environ['CRIER_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`Pronto: aún no se ofrece 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.usecrier.com/v1/inbox/conversations" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/conversations', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/conversations",
headers={"Authorization": f"Bearer {os.environ['CRIER_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`Pronto: aún no se ofrece #### 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.usecrier.com/v1/inbox/conversations/cnv_…/messages" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/conversations/cnv_…/messages', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/conversations/cnv_…/messages",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]
```
## Enviar un mensaje [Sección titulada «Enviar un mensaje»](#enviar-un-mensaje) POST`/v1/inbox/conversations/{id}/messages`Pronto: aún no se ofrece 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`stringobligatorio La cuenta a la que pertenece. * `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 204 Sin contenido * curl
```bash
curl -X POST "https://api.usecrier.com/v1/inbox/conversations/cnv_…/messages" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/conversations/cnv_…/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/inbox/conversations/cnv_…/messages",
headers={"Authorization": f"Bearer {os.environ['CRIER_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`Pronto: aún no se ofrece #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`stringobligatorio La cuenta a la que pertenece. #### Respuesta 204 Sin contenido * curl
```bash
curl -X POST "https://api.usecrier.com/v1/inbox/conversations/cnv_…/read" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/conversations/cnv_…/read', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/inbox/conversations/cnv_…/read",
headers={"Authorization": f"Bearer {os.environ['CRIER_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}`Pronto: aún no se ofrece #### Parámetros * `id`stringobligatorio #### Cuerpo * `accountId`stringobligatorio La cuenta a la que pertenece. * `status`stringobligatorio Valores: `active` · `archived` #### Respuesta 204 Sin contenido * curl
```bash
curl -X PATCH "https://api.usecrier.com/v1/inbox/conversations/cnv_…" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/conversations/cnv_…', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/inbox/conversations/cnv_…",
headers={"Authorization": f"Bearer {os.environ['CRIER_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 Crier. #### 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.usecrier.com/v1/inbox/posts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/posts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/posts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/posts/thr_…/comments" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/posts/thr_…/comments', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/posts/thr_…/comments",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/posts/thr_…/comments" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m",
"text": "Thank you!"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/posts/thr_…/comments', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/inbox/posts/thr_…/comments",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/posts/thr_…/comments/cmt_…" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/posts/thr_…/comments/cmt_…', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/inbox/posts/thr_…/comments/cmt_…",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/posts/thr_…/comments/cmt_…" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/inbox/posts/thr_…/comments/cmt_…', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/inbox/posts/thr_…/comments/cmt_…",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/mentions?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/mentions?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/mentions?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/inbox/mentions/mtn_…/reply" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/inbox/mentions/mtn_…/reply', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/inbox/mentions/mtn_…/reply",
headers={"Authorization": f"Bearer {os.environ['CRIER_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`Pronto: aún no se ofrece 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.usecrier.com/v1/inbox/reviews" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/reviews', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/reviews",
headers={"Authorization": f"Bearer {os.environ['CRIER_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`Pronto: aún no se ofrece #### 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.usecrier.com/v1/inbox/reviews/rev_…/reply" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/inbox/reviews/rev_…/reply', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/inbox/reviews/rev_…/reply",
headers={"Authorization": f"Bearer {os.environ['CRIER_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`Pronto: aún no se ofrece 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.usecrier.com/v1/inbox/reviews/rev_…/reply" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/inbox/reviews/rev_…/reply', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/inbox/reviews/rev_…/reply",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
```
# Multimedia
> Sube imágenes y vídeos a Crier antes de publicarlos.
Sube imágenes y vídeos a Crier 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.usecrier.com/v1/media/upload-url" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "autumn.mp4",
"contentType": "video/mp4",
"size": 48211234
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/media/upload-url', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/media/upload-url",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"filename": "autumn.mp4",
"contentType": "video/mp4",
"size": 48211234
},
)
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`. #### 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.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_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` Las más recientes primero. #### Parámetros * `limit`integer máx. 100 #### Respuesta 200 * curl
```bash
curl "https://api.usecrier.com/v1/posts?limit=20" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts?limit=20', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/posts?limit=20",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/import" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/import', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/import",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['CRIER_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 borra de Crier. Si sigue publicada, retírala antes. #### Parámetros * `id`stringobligatorio #### Respuesta 204 Sin contenido * curl
```bash
curl -X DELETE "https://api.usecrier.com/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/edit" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/edit', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/edit",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/metrics" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/metrics', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/metrics",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/cancel" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/cancel', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/cancel",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/review" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/review",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/retry" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/retry', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/retry",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/unpublish" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/unpublish', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/posts/pst_7q1w0e/unpublish",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/profiles" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/profiles', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/profiles",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/profiles" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme",
"timezone": "Europe/Madrid",
"externalId": "customer-42"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/profiles', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/profiles",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Spain"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d/queue', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
```
# 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.usecrier.com/v1/team" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/team', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/team",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/team/invitations" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/team/invitations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/team/invitations",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/team/invitations/inv_9n1m4l" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/team/invitations/inv_9n1m4l', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/team/invitations/inv_9n1m4l",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/team/members/{userId}" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/team/members/{userId}', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/team/members/{userId}",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/team/members/{userId}" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/team/members/{userId}', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/team/members/{userId}",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/invitations/accept" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/invitations/accept', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.post(
"https://api.usecrier.com/v1/invitations/accept",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]
```
# Webhooks
> Recibe los eventos de Crier en tu endpoint HTTPS.
Recibe los eventos de Crier 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.usecrier.com/v1/webhook-endpoint" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/webhook-endpoint', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/webhook-endpoint" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.acme.com/webhooks/crier"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/webhook-endpoint', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"url": "https://app.acme.com/webhooks/crier"
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.usecrier.com/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"url": "https://app.acme.com/webhooks/crier"
},
)
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.usecrier.com/v1/webhook-endpoint" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
await fetch('https://api.usecrier.com/v1/webhook-endpoint', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
```
* Python
```python
import os, requests
requests.delete(
"https://api.usecrier.com/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
```
# 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.usecrier.com/v1/me" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/me', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/me",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/workspace" \
-H "Authorization: Bearer $CRIER_API_KEY"
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/workspace', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.get(
"https://api.usecrier.com/v1/workspace",
headers={"Authorization": f"Bearer {os.environ['CRIER_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. #### Respuesta 200 * curl
```bash
curl -X PATCH "https://api.usecrier.com/v1/workspace" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"usage": "api"
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/workspace', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_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.usecrier.com/v1/workspace",
headers={"Authorization": f"Bearer {os.environ['CRIER_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.usecrier.com/v1/webhook-endpoint" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.acme.com/webhooks/crier",
"events": [
"post.published",
"post.failed",
"account.disconnected"
]
}'
```
* Node
```js
const res = await fetch('https://api.usecrier.com/v1/webhook-endpoint', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"url": "https://app.acme.com/webhooks/crier",
"events": [
"post.published",
"post.failed",
"account.disconnected"
]
}),
});
const { data } = await res.json();
```
* Python
```python
import os, requests
res = requests.put(
"https://api.usecrier.com/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"url": "https://app.acme.com/webhooks/crier",
"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 | `post` | | `post.cancelled` | Se canceló | `post` | | `post.removed` | Se retiró de una red | `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` | | `account.connected` | Se conectó una cuenta | `account` | | `account.disconnected` | Se desconectó o hay que reconectarla | `account` | | `message.received` (pronto) | Alguien escribió un mensaje directo | `accountId`, `conversationId`, `message` | | `comment.received` | Alguien comentó una publicación | `accountId`, `postId`, `comment` | | `review.received` (pronto) | Llegó una reseña nueva (Google Business) | `accountId`, `review` | 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 `Crier-Event`, `Crier-Event-Id` y `Crier-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 verifyCrierSignature = (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_crier_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 `Crier-Event-Id` para no procesarlo dos veces.