API pública + n8n
Para creadores y administradores de clubes que ya gestionan su contenido con automatizaciones: envía una publicación a Amator desde n8n, un script o cualquier herramienta capaz de hacer una petición HTTP.
Qué hace
Un único endpoint publica un texto en tu nombre, en uno de dos sitios:
- En tu feed personal: simplemente omite
club_id. - En un club que gestionas: envía su
club_id. Tienes que ser el propietario o un administrador del club, la misma regla que para publicar como club en la app.
Consigue una clave API
- Abre la app de Amator y ve a Ajustes › Claves API.
- Toca Crear y ponle a la clave un nombre que reconozcas después, por ejemplo «n8n».
- Copia la clave enseguida: solo se muestra una vez. Si la pierdes, revócala y crea otra.
Trata la clave como una contraseña: quien la tenga puede publicar en tu nombre. Puedes revocar cualquier clave en cualquier momento desde la misma pantalla, y a partir de entonces se rechazan las peticiones que la usen.
El endpoint
POST https://api.amator.app/api/v1/public/posts
Envía un cuerpo JSON y la clave en la cabecera X-API-KEY (no Authorization: Bearer).
contentstring — el texto de la publicación, de 1 a 2000 caracteres. Obligatorio.club_iduuid | null — el club en cuyo nombre publicas. Opcional: sin él, la publicación va a tu feed personal.
Publicar en tu feed personal
curl -X POST https://api.amator.app/api/v1/public/posts \
-H "X-API-KEY: YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"content":"Training moved to 19:00 tonight"}'Publicar como club
curl -X POST https://api.amator.app/api/v1/public/posts \
-H "X-API-KEY: YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"content":"Match day! Kick-off at 18:00","club_id":"00000000-0000-0000-0000-000000000000"}'Una publicación correcta devuelve 201 con su enlace:
HTTP/1.1 201 Created
{
"success": true,
"data": {
"id": "…",
"destination": "club",
"club_id": "00000000-0000-0000-0000-000000000000",
"created_at": "2026-10-05T18:00:00.000Z",
"url": "https://web.amator.app/posts/…"
},
"requestId": "…"
}Una publicación por hora, por destino
Cada destino tiene su propio cupo por hora: tu perfil es uno y cada club es otro. Los cupos nunca se suman: publicar en uno no gasta el de otro, y un destino libre no ayuda a uno ocupado.
- OK Tu perfil y el club A en la misma hora
- OK Los clubes A, B y C en la misma hora
- 429 Una segunda publicación en el club A dentro de la hora: 429, aunque tu perfil y los demás clubes estén libres
Si el cupo está ocupado, recibes 429 con la cabecera Retry-After (en segundos) y los detalles en el cuerpo:
HTTP/1.1 429 Too Many Requests
Retry-After: 2400
{
"success": false,
"error": {
"code": "PUBLIC_API_RATE_LIMITED",
"message": "This club already had its post this hour",
"details": {
"destination": "club",
"club_id": "00000000-0000-0000-0000-000000000000",
"retry_after_seconds": 2400,
"next_allowed_at": "2026-10-05T19:00:00.000Z"
}
},
"requestId": "…"
}Espera al menos Retry-After segundos, o hasta next_allowed_at, antes de volver a publicar en ese destino. No reintentes en bucle.
Otras respuestas
- 400 FEED_POST_EMPTYEl texto está vacío o es demasiado largo.
- 401 PUBLIC_API_KEY_INVALIDFalta la clave, es desconocida o está revocada.
- 403 FEED_NOT_A_CAPTAINNo eres propietario ni administrador de ese club.
- 404 FEED_TEAM_NOT_FOUNDNo existe ningún club con ese
club_id. - 429 PUBLIC_API_RATE_LIMITEDEse destino ya tuvo una publicación en esta hora.
- 429 FEED_DAILY_LIMIT_REACHEDSe alcanzó el límite propio del feed: 40 publicaciones al día.
Workflow de n8n listo para usar
Cinco nodos: un inicio manual, un nodo Edit Fields con content y club_id, un nodo If que comprueba si club_id está vacío y dos nodos HTTP Request: uno publica en tu perfil y el otro en el club.
Empieza con un disparador manual para que puedas probarlo nada más importarlo. Cuando funcione, sustituye Start por lo que de verdad debe lanzarlo —Schedule, RSS, un formulario— y asigna su salida a los dos campos.
{
"name": "Amator — publish a post",
"nodes": [
{
"id": "7b0f3a52-1c6e-4d1b-9a43-5e2f8c1d0a01",
"name": "Start",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"parameters": {}
},
{
"id": "7b0f3a52-1c6e-4d1b-9a43-5e2f8c1d0a02",
"name": "Post content",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
220,
0
],
"parameters": {
"mode": "manual",
"assignments": {
"assignments": [
{
"id": "7b0f3a52-1c6e-4d1b-9a43-5e2f8c1d0b01",
"name": "content",
"value": "Hello from n8n! Training moved to 19:00 tonight.",
"type": "string"
},
{
"id": "7b0f3a52-1c6e-4d1b-9a43-5e2f8c1d0b02",
"name": "club_id",
"value": "",
"type": "string"
}
]
},
"options": {}
}
},
{
"id": "7b0f3a52-1c6e-4d1b-9a43-5e2f8c1d0a03",
"name": "Club ID empty?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
440,
0
],
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose",
"version": 2
},
"conditions": [
{
"id": "7b0f3a52-1c6e-4d1b-9a43-5e2f8c1d0c01",
"leftValue": "={{ $json.club_id }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "empty",
"singleValue": true
}
}
],
"combinator": "and"
},
"looseTypeValidation": true,
"options": {}
}
},
{
"id": "7b0f3a52-1c6e-4d1b-9a43-5e2f8c1d0a04",
"name": "Post to my profile",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
680,
-120
],
"parameters": {
"method": "POST",
"url": "https://api.amator.app/api/v1/public/posts",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "X-API-KEY",
"value": "YOUR_API_KEY_HERE"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ content: $json.content }) }}",
"options": {}
}
},
{
"id": "7b0f3a52-1c6e-4d1b-9a43-5e2f8c1d0a05",
"name": "Post to club",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
680,
120
],
"parameters": {
"method": "POST",
"url": "https://api.amator.app/api/v1/public/posts",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "X-API-KEY",
"value": "YOUR_API_KEY_HERE"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ content: $json.content, club_id: $json.club_id }) }}",
"options": {}
}
}
],
"connections": {
"Start": {
"main": [
[
{
"node": "Post content",
"type": "main",
"index": 0
}
]
]
},
"Post content": {
"main": [
[
{
"node": "Club ID empty?",
"type": "main",
"index": 0
}
]
]
},
"Club ID empty?": {
"main": [
[
{
"node": "Post to my profile",
"type": "main",
"index": 0
}
],
[
{
"node": "Post to club",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {},
"pinData": {}
}
Impórtalo en n8n
- Copia el JSON de arriba o descarga el archivo.
- En n8n ve a Workflows, crea un workflow nuevo y pega el JSON en el lienzo vacío (Ctrl/Cmd+V). Para el archivo, usa el menú ⋯ › Import from File.
- En los dos nodos HTTP Request sustituye
YOUR_API_KEY_HEREpor tu clave. Mejor aún: guárdala como credencial de n8n (Header Auth, nombreX-API-KEY). - En Post content escribe tu texto en
content. Dejaclub_idvacío para publicar en tu perfil o pega el ID del club para publicar como club. - Pulsa Execute workflow. El nodo HTTP muestra la respuesta: 201 y la
urlde la publicación si todo va bien.