Skip to content
Learni
View all tutorials
Outils Collaboration

Comment automatiser Confluence via son API REST en 2026

Introduction

Confluence, l'outil de collaboration Atlassian, est indispensable pour centraliser la documentation d'entreprise, les wikis techniques et les playbooks DevOps. En 2026, avec l'essor des pipelines CI/CD et des automatisations IA, maîtriser son API REST devient critique pour scaler les workflows. Imaginez générer automatiquement des pages de release notes depuis Jira, importer des rapports depuis GitHub, ou migrer des milliers de pages sans intervention manuelle.

Ce tutoriel avancé vous guide pas à pas pour créer un bot Node.js qui interagit avec l'API Confluence Cloud : authentification token-based, création de spaces/pages, uploads d'attachments, queries CQL avancées et gestion d'erreurs robuste. Chaque script est complet et fonctionnel, prêt à copier-coller. À la fin, vous automatiserez vos flux comme un pro, économisant des heures par sprint. Idéal pour architectes DevOps ou admins Atlassian gérant des instances >10k pages.

Prérequis

  • Compte Confluence Cloud Premium ou Enterprise (API rate limits plus élevés)
  • Node.js 20+ installé (vérifiez avec node -v)
  • Éditeur de code comme VS Code avec extension TypeScript
  • Connaissances avancées en TypeScript, API REST et async/await
  • Accès admin ou permission 'Create Space' sur Confluence

Initialiser le projet Node.js

terminal
mkdir confluence-bot
cd confluence-bot
npm init -y
npm install axios dotenv typescript ts-node @types/node
npm install -D @types/axios
npx tsc --init
mkdir src

Ce script bash crée un projet Node.js dédié, installe Axios pour les appels HTTP, Dotenv pour les variables d'environnement, et configure TypeScript. Il prépare un setup zéro-friction avec ts-node pour exécuter directement les .ts. Évitez les globals : utilisez toujours un package.json dédié.

Obtenir votre token API Confluence

Allez dans Atlassian Account Settings > Security > API Tokens > Create token. Nommez-le 'confluence-bot-2026'. Copiez le token (format ~abcd1234). Utilisez votre email Atlassian comme username pour Basic Auth. Stockez-les sécuritairement dans .env, jamais en dur. Rate limit : 100 req/min en Premium, surveillez les headers X-Seraph-LoginReason pour debug.

Configurer package.json

package.json
{
  "name": "confluence-bot",
  "version": "1.0.0",
  "main": "src/index.ts",
  "scripts": {
    "start": "ts-node src/index.ts",
    "dev": "ts-node --watch src/index.ts"
  },
  "dependencies": {
    "axios": "^1.7.2",
    "dotenv": "^16.4.5",
    "typescript": "^5.5.3",
    "ts-node": "^10.9.2",
    "@types/node": "^22.3.0"
  },
  "devDependencies": {
    "@types/axios": "^0.14.0"
  }
}

Ce package.json complet ajoute des scripts start et dev pour lancer le bot facilement. Axios gère les requêtes HTTPS avec retry auto, Dotenv charge les secrets. TypeScript strict pour catcher les erreurs compile-time. Lancez avec npm run dev pour hot-reload en dev.

Fichier d'environnement .env

.env
CONFLUENCE_BASE_URL=https://votre-site.atlassian.net/wiki
CONFLUENCE_EMAIL=votre.email@entreprise.com
CONFLUENCE_API_TOKEN=ATATT3x...VotreTokenComplet
SPACE_KEY=MYSPACE

Remplacez par vos vraies valeurs : BASE_URL sans /api, SPACE_KEY du space cible (trouvé via /spaces). Ajoutez .env à .gitignore. Dotenv le charge auto. Piège : URL sans 'https://' ou trailing slash cause 404 ; testez avec curl d'abord.

Implémenter l'authentification et lister les spaces

L'API Confluence utilise Basic Auth (email:token base64). Testez d'abord manuellement : curl -u email:token $BASE_URL/rest/api/space. Notre client Axios encapsule ça. Ce premier script liste les spaces pour valider l'auth, avec gestion d'erreurs 401/429.

Client API de base avec auth

src/confluenceClient.ts
import axios, { AxiosInstance, AxiosError } from 'axios';
import dotenv from 'dotenv';

dotenv.config();

const config = {
  baseURL: process.env.CONFLUENCE_BASE_URL + '/rest/api',
  auth: {
    username: process.env.CONFLUENCE_EMAIL!,
    password: process.env.CONFLUENCE_API_TOKEN!
  },
  headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }
};

export const client: AxiosInstance = axios.create(config);

client.interceptors.response.use(
  (response) => response,
  (error: AxiosError) => {
    if (error.response?.status === 429) {
      console.error('Rate limit atteinte, attendez 1min');
      throw error;
    }
    console.error('Erreur API:', error.response?.data || error.message);
    throw error;
  }
);

export async function listSpaces(): Promise<any[]> {
  const res = await client.get('/space');
  return res.data.results;
}

// Test
(async () => {
  try {
    const spaces = await listSpaces();
    console.log('Spaces:', spaces.map((s: any) => ({ key: s.key, name: s.name })));
  } catch (err) {
    console.error('Échec:', err);
  }
})();

Ce client Axios réutilisable gère auth Basic, baseURL, headers et intercepteur pour rate limits (retry manuel requis). listSpaces() fetch tous les spaces avec paginaison implicite. Lancez npm run start : output JSON valide ou erreur debuggée. Piège : token expiré → 401, régénérez-le.

Créer un space programmatiquement

Permissions requises : 'Create Space' global. L'endpoint /space POST crée un space 'global' ou 'personal'. Utilisez type: 'global' pour équipes. Réponse inclut id et key pour refs futures.

Fonction créer space

src/createSpace.ts
import { client } from './confluenceClient';

export async function createSpace(name: string, key: string): Promise<any> {
  const payload = {
    type: 'global',
    status: 'current',
    name,
    key,
    description: { plain: { value: 'Space créé via API en 2026', representation: 'plain' } }
  };
  const res = await client.post('/space', payload);
  console.log('Space créé:', res.data);
  return res.data;
}

// Usage
(async () => {
  await createSpace('Mon Bot Space', 'BOTSPACE');
})();

Payload minimal mais complet : key unique (majuscules, no spaces). Description en 'plain' évite parsing HTML. Retourne l'objet space full. Erreur courante : key existant → 409 Conflict, checkez d'abord via listSpaces(). Intégrez en pipeline GitHub Actions.

Gérer les pages et contenus

Les pages sont des 'content' de type 'page'. Créez sous un parent (root ou page existante). Utilisez body.storage pour HTML riche, ou editor2 pour ADF (nouveau format 2026). Versionning auto.

Créer et updater une page

src/managePages.ts
import { client } from './confluenceClient';

export async function createPage(spaceKey: string, title: string, bodyHtml: string, parentId?: string): Promise<any> {
  const payload = {
    type: 'page',
    status: 'current',
    space: { key: spaceKey },
    title,
    body: {
      storage: {
        value: bodyHtml,
        representation: 'storage'
      }
    },
    ...(parentId && { parent: { id: parentId } })
  };
  const res = await client.post('/content', payload);
  console.log('Page créée ID:', res.data.id);
  return res.data;
}

export async function updatePage(pageId: string, version: number, bodyHtml: string): Promise<any> {
  const payload = {
    id: pageId,
    type: 'page',
    title: 'Titre mis à jour',
    version: { number: version + 1 },
    body: {
      storage: { value: bodyHtml, representation: 'storage' }
    }
  };
  const res = await client.put(`/content/${pageId}`, payload);
  console.log('Page updatée, nouvelle version:', res.data.version.number);
  return res.data;
}

// Usage exemple
(async () => {
  const page = await createPage('BOTSPACE', 'Page Bot Test', '<h1>Hello 2026!</h1><p>Automatisé.</p>');
  await updatePage(page.id, page.version.number, '<h1>Mis à jour!</h1><p>Version 2.</p>');
})();

Création avec parentId pour hiérarchie. Update incrémente version obligatoirement (fetch via GET /content/{id} d'abord). HTML valide en 'storage' (macro support). Piège : body sans 'representation' → 400 Bad Request. Scalez pour 100+ pages en batch.

Uploader un attachment

src/uploadAttachment.ts
import { client } from './confluenceClient';
import fs from 'fs';

export async function uploadAttachment(pageId: string, filePath: string): Promise<any> {
  if (!fs.existsSync(filePath)) throw new Error('Fichier non trouvé');
  const formData = new FormData();
  formData.append('file', fs.createReadStream(filePath), { filename: filePath.split('/').pop() });
  formData.append('comment', 'Upload auto 2026');

  const res = await client.post(`/content/${pageId}/child/attachment`, formData, {
    headers: formData.getHeaders()
  });
  console.log('Attachment uploadé:', res.data);
  return res.data;
}

// Ajoutez npm install form-data @types/form-data pour FormData polyfill si besoin
// Usage
// await uploadAttachment('123456', './rapport.pdf');

Utilise FormData pour multipart upload sur /child/attachment. fs.createReadStream pour gros fichiers (>100MB OK en Enterprise). Comment auto pour audit trail. Piège Node : FormData natif ES2023, sinon installez 'form-data'. Versionne attachments comme pages.

Queries avancées avec CQL

CQL (Confluence Query Language) filtre comme SQL : type=page and space=KEY and text~"mot-clé". Paginer avec start/limit. Idéal pour rapports automatisés ou cleanups.

Query CQL pour pages

src/cqlQuery.ts
import { client } from './confluenceClient';

export async function searchPages(cql: string, start = 0, limit = 25): Promise<any> {
  const params = new URLSearchParams({ cql, start: start.toString(), limit: limit.toString() });
  const res = await client.get(`/content/search?${params.toString()}`);
  console.log(`Résultats (${res.data.size}/${res.data.totalSize}):`, res.data.results.map((p: any) => ({ id: p.id, title: p.title }))) ;
  return res.data;
}

// Usage avancées
(async () => {
  await searchPages('type=page and space=BOTSPACE and created >= -1d');
  await searchPages('type=page and text ~ "erreur"', 0, 100);
})();

CQL full-text search avec opérateurs (and, ~ fuzzy). Pagination manuelle pour >500 résultats. totalSize pour loops. Performant vs GET /space/{key}/page. Piège : CQL malformé → 400 ; testez dans Confluence UI 'Advanced Search' d'abord.

Bonnes pratiques

  • Rate limiting : Implémentez exponential backoff (p-setTimeout) pour >50 req/min ; utilisez webhooks pour events push au lieu de polling.
  • Sécurité : Rotatez tokens tous 90j ; utilisez App Links OAuth2 pour apps server-side (plus scalable que Basic).
  • Error handling : Loggez toujours error.response.data ; retry idempotents (POST/PUT) max 3x.
  • Scalabilité : Batch via /bulk endpoint ; migrez vers GraphQL beta si Premium+.
  • Tests : Mockez Axios avec MSW ; CI/CD avec Playwright pour end-to-end.

Erreurs courantes à éviter

  • 401 Unauthorized : Token invalide/expiré ou email faux ; vérifiez base64 echo -n 'email:token' | base64.
  • 409 Conflict : Space/page key dupliqué ou version obsolète ; fetch latest avant update.
  • 413 Payload Too Large : Attachments >2GB foirent ; chunker ou utilisez S3 proxy.
  • CQL vide : Toujours limit<100 sinon timeout ; pas de wildcards % (utilisez ~).

Pour aller plus loin

  • Docs officielles : API Confluence REST
  • Plugins avancés : ScriptRunner pour Groovy in-app ; Forge pour apps custom.
  • Intégrez avec Jira : /rest/api/3/issue sync.
  • Découvrez nos formations Learni sur Atlassian DevOps pour CI/CD complets.
  • Repo GitHub exemple : fourni en fin d'article (forkez-le !)