API publique + n8n

Pour les créateurs et les administrateurs de club qui gèrent déjà leur contenu par automatisation : envoyez une publication à Amator depuis n8n, un script ou tout outil capable d’envoyer une requête HTTP.

Ce que ça fait

Un seul endpoint publie un texte en votre nom, à l’un de deux endroits :

  • Sur votre fil personnel — omettez simplement club_id.
  • Dans un club que vous gérez — transmettez son club_id. Vous devez en être le propriétaire ou un administrateur, la même règle que pour publier au nom du club dans l’app.

Obtenir une clé API

  1. Ouvrez l’app Amator et allez dans Réglages › Clés API.
  2. Touchez Créer et donnez à la clé un nom que vous reconnaîtrez, par exemple « n8n ».
  3. Copiez la clé tout de suite : elle n’est affichée qu’une seule fois. Si vous la perdez, révoquez-la et créez-en une autre.

Traitez la clé comme un mot de passe : quiconque la détient peut publier en votre nom. Vous pouvez révoquer n’importe quelle clé à tout moment sur le même écran ; les requêtes qui l’utilisent sont alors refusées.

L’endpoint

POST https://api.amator.app/api/v1/public/posts

Envoyez un corps JSON et la clé dans l’en-tête X-API-KEY (pas Authorization: Bearer).

  • content string — le texte de la publication, de 1 à 2000 caractères. Obligatoire.
  • club_id uuid | null — le club au nom duquel vous publiez. Facultatif — sans lui, la publication va sur votre fil personnel.

Publier sur votre fil personnel

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"}'

Publier au nom d’un 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"}'

Une publication réussie renvoie 201 avec son lien :

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": "…"
}

Une publication par heure, par destination

Chaque destination a son propre créneau horaire : votre profil en est un, chaque club en est un autre. Les créneaux ne sont jamais mis en commun — publier à un endroit n’en consomme pas un autre, et une destination libre n’aide pas une destination occupée.

  • OK Votre profil et le club A dans la même heure
  • OK Les clubs A, B et C dans la même heure
  • 429 Une deuxième publication dans le club A dans l’heure — 429, même si votre profil et les autres clubs sont libres

Si le créneau est pris, vous recevez 429 avec l’en-tête Retry-After (en secondes) et les détails dans le corps :

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": "…"
}

Attendez au moins Retry-After secondes, ou jusqu’à next_allowed_at, avant de republier vers cette destination. Ne réessayez pas en boucle.

Autres réponses

  • 400 FEED_POST_EMPTY
    Le texte est vide ou trop long.
  • 401 PUBLIC_API_KEY_INVALID
    La clé est absente, inconnue ou révoquée.
  • 403 FEED_NOT_A_CAPTAIN
    Vous n’êtes ni propriétaire ni administrateur de ce club.
  • 404 FEED_TEAM_NOT_FOUND
    Aucun club ne correspond à ce club_id.
  • 429 PUBLIC_API_RATE_LIMITED
    Cette destination a déjà reçu une publication cette heure-ci.
  • 429 FEED_DAILY_LIMIT_REACHED
    La limite propre au fil, 40 publications par jour, est atteinte.

Workflow n8n prêt à l’emploi

Cinq nœuds : un démarrage manuel, un nœud Edit Fields contenant content et club_id, un nœud If qui vérifie si club_id est vide, et deux nœuds HTTP Request — l’un publie sur votre profil, l’autre dans le club.

Il commence par un déclencheur manuel pour que vous puissiez le tester dès l’import. Une fois qu’il fonctionne, remplacez Start par ce qui doit vraiment le lancer — Schedule, RSS, un formulaire — et reliez sa sortie aux deux champs.

{
  "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": {}
}

L’importer dans n8n

  1. Copiez le JSON ci-dessus ou téléchargez le fichier.
  2. Dans n8n, allez dans Workflows, créez un nouveau workflow et collez le JSON sur le canevas vide (Ctrl/Cmd+V). Pour le fichier, passez par le menu ⋯ › Import from File.
  3. Dans les deux nœuds HTTP Request, remplacez YOUR_API_KEY_HERE par votre clé. Mieux encore : enregistrez-la comme identifiant n8n (Header Auth, nom X-API-KEY).
  4. Dans Post content, écrivez votre texte dans content. Laissez club_id vide pour publier sur votre profil, ou collez l’ID du club pour publier en son nom.
  5. Cliquez sur Execute workflow. Le nœud HTTP affiche la réponse — 201 et l’url de la publication en cas de succès.