Public API + n8n
For creators and club admins who already run their content through automations: send a post to Amator from n8n, a script or any tool that can make an HTTP request.
What it does
One endpoint publishes a text post on your behalf, to one of two places:
- Your personal feed — just leave
club_idout. - A club you run — pass its
club_id. You have to be the club’s owner or admin, the same rule as posting as the club in the app.
Get an API key
- Open the Amator app and go to Settings › API keys.
- Tap Create and give the key a name you will recognise later, e.g. “n8n”.
- Copy the key straight away — it is shown only once. If you lose it, revoke it and create a new one.
Treat the key like a password: anyone who has it can post as you. You can revoke any key at any time on the same screen, and requests made with it are refused from then on.
The endpoint
POST https://api.amator.app/api/v1/public/posts
Send a JSON body and put the key in the X-API-KEY header (not Authorization: Bearer).
contentstring — the post text, 1–2000 characters. Required.club_iduuid | null — the club to post as. Optional — without it the post goes to your personal feed.
Post to your personal feed
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"}'Post as a 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"}'A successful post returns 201 with a link to it:
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": "…"
}One post per hour, per destination
Every destination has its own hourly slot: your profile is one, and each club is another. Slots are never pooled — posting to one does not use up another, and a free slot elsewhere does not help a busy one.
- OK Your profile and club A in the same hour
- OK Clubs A, B and C in the same hour
- 429 A second post to club A within the hour — 429, even if your profile and the other clubs are free
When a slot is taken you get 429 with a Retry-After header (in seconds) and the details in the body:
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": "…"
}Wait at least Retry-After seconds, or until next_allowed_at, before posting to that destination again. Do not retry in a loop.
Other responses
- 400 FEED_POST_EMPTYThe post text is empty or too long.
- 401 PUBLIC_API_KEY_INVALIDThe key is missing, unknown or revoked.
- 403 FEED_NOT_A_CAPTAINYou are not the owner or an admin of that club.
- 404 FEED_TEAM_NOT_FOUNDThere is no club with that
club_id. - 429 PUBLIC_API_RATE_LIMITEDThat destination already had a post this hour.
- 429 FEED_DAILY_LIMIT_REACHEDThe feed’s own limit of 40 posts a day has been reached.
Ready-made n8n workflow
Five nodes: a manual start, an Edit Fields node holding content and club_id, an If node that checks whether club_id is empty, and two HTTP Request nodes — one posts to your profile, the other to the club.
It starts with a manual trigger so you can test it right after importing. Once it works, replace Start with whatever should really kick it off — Schedule, RSS, a form — and map its output to the two fields.
{
"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": {}
}
Import it into n8n
- Copy the JSON above, or download the file.
- In n8n go to Workflows, create a new workflow and paste the copied JSON onto the empty canvas (Ctrl/Cmd+V). To use the file, open the ⋯ menu › Import from File.
- In both HTTP Request nodes replace
YOUR_API_KEY_HEREwith your key. Better still, store it as an n8n credential (Header Auth, nameX-API-KEY). - In Post content, write your text in
content. Leaveclub_idempty to post to your profile, or paste the club’s ID to post as the club. - Click Execute workflow. The HTTP node shows the response — 201 and the post’s
urlon success.