Chaque sprint commence avec un tableau rempli de tickets et une équipe qui a besoin d’un endroit propre pour travailler. Pour les agences qui gèrent des projets WordPress sur des cycles de deux semaines, cela signifie qu’il faut créer un environnement de staging dans MyKinsta avant que le premier ticket ne soit pris en compte.
Cela ne prend que quelques minutes, mais c’est le genre de tâche qui passe entre les mailles du filet parce qu’elle semble triviale.
L’API Kinsta peut supprimer cette étape. Lorsqu’un sprint démarre dans Jira, vous pouvez configurer un crochet web qui déclenche un évènement dans l’intergiciel, qui lit alors la charge utile, l’associe à un site Kinsta et appelle l’API pour créer un nouvel environnement de staging.
Pourquoi les agences devraient automatiser le provisionnement de l’environnement
Créer un environnement après avoir planifié un sprint signifie ouvrir MyKinsta, trouver le bon site client parmi une liste de dizaines, créer et nommer un environnement, puis revenir à Jira. Bien que cela ne soit pas compliqué, cela doit se faire au bon moment, à chaque fois, et pour chaque projet client en cours.
Ne pas le faire signifie qu’une équipe commence à travailler dans l’environnement du dernier sprint. À partir de là, les changements s’accumulent les uns sur les autres, et lorsqu’il y a un bogue, l’isoler s’apparente plus à de l’archéologie qu’à du débogage.
Ce dont vous avez besoin avant de commencer
Pour connecter l’API Kinsta et Jira, vous avez besoin d’un compte Kinsta avec au moins un site WordPress dans un environnement existant, un compte Jira Cloud avec un accès administrateur pour configurer les crochets web, et Node.js installé localement.
Pour vous authentifier avec l’API Kinsta, naviguez vers [Votre entreprise] > Réglages de l’entreprise > Clés API dans MyKinsta et cliquez sur Créer une clé API.

Ensuite, donnez un nom à la clé, définissez une durée d’expiration et cliquez sur Générer. La clé n’est affichée qu’une seule fois, alors notez-la avant de continuer.
Vous la placez dans un fichier .env à la racine du projet avec l’identifiant de votre entreprise Kinsta, que vous pouvez trouver sous Réglages de l’entreprise > Détails de facturation :
KINSTA_API_KEY=your_api_key_here
KINSTA_COMPANY_ID=your_company_id_here
Obtenir vos identifiants de site Jira et Kinsta
Vous avez besoin de l’ID du site Kinsta pour chaque projet client dans l’automatisation. Il s’agit d’un UUID que Kinsta attribue lors de la création du site. Il apparait dans l’URL MyKinsta lorsque vous ouvrez un site ou par l’appel GET /sites une fois que votre clé API est en place :
https://my.kinsta.com/sites/details/fbab4927-e354-4044-b226-29ac0fbd20ca/…
Du côté de Jira, vous avez besoin de l’identifiant numérique de chaque projet que vous souhaitez connecter. Il apparait dans l’URL (ici comme 2) :
https://your-domain.atlassian.net/jira/software/projects/SCRUM/boards/2
C’est la même valeur que Jira inclut dans le payload du webhook sprint_started comme originBoardId. La correspondance entre les ID de conseil et les ID de site se trouve dans votre fichier .env :
BOARD_ID_CLIENT_A=2
SITE_ID_CLIENT_A=fbab4927-e354-4044-b226-29ac0fbd20ca
BOARD_ID_CLIENT_B=5
SITE_ID_CLIENT_B=44b5a6d1-c83f-4b0e-9a1c-2e7dbc903fa1
De plus, pour le développement local, Jira ne peut pas atteindre directement l’hôte local. Ngrok peut être utilisé pour exposer un port local à l’internet avec une URL publique temporaire, que vous pouvez utiliser comme point de terminaison de votre crochet web pendant le développement. Une fois que vous avez déployé une adresse middleware, vous pouvez la remplacer.
Comment automatiser le provisionnement de l’environnement de sprint avec Jira et l’API Kinsta
Cette intégration s’effectue sur deux systèmes. Dans Jira, un webhook se déclenche lorsqu’un sprint démarre et transmet la charge utile de l’évènement à votre middleware. Pour Kinsta, l’intergiciel lit l’ID du conseil à partir de la charge utile, le résout en ID de site à l’aide de la carte de configuration et appelle l’API Kinsta pour créer un environnement de staging simple nommé d’après le sprint.
1. Enregistrer un webhook Jira pour les évènements de sprint
Jira Cloud vous propose deux façons d’enregistrer un webhook. L’option la plus simple pour la plupart des équipes est l’interface utilisateur Jira. L’option Réglages > Système se trouve dans le menu supérieur droit :

De là, choisissez Avancé > WebHooks, puis cliquez sur Créer un WebHook :

Ici, saisissez un nom, collez une URL d’intergiciel avec /sprint en annexe (une option factice est suffisante pour l’instant), et sous Évènements, sélectionnez Sprint > démarré. Cela crée un webhook administrateur, qui se déclenche pour chaque évènement sprint_started dans l’ensemble de votre instance Jira.

La deuxième option est l’API REST, en utilisant POST /rest/webhooks/1.0/webhook. Cela fonctionne bien lorsque l’enregistrement du crochet web fait partie d’un script de déploiement :
curl -X POST \
https://your-domain.atlassian.net/rest/webhooks/1.0/webhook \
-u [email protected]:your-api-token \
-H 'Content-Type: application/json' \
-d '{
"name": "Sprint provisioning webhook",
"url": "https://your-middleware-url.com/sprint",
"events": ["sprint_started"],
"filters": {},
"excludeBody": false
}'
L’appel à PUT /rest/webhooks/1.0/webhook/refresh ajoute une extension au délai d’expiration de 30 jours pour le webhook. Lorsque Jira déclenche sprint_started, la charge utile arrive à votre point de terminaison sous la forme d’un POST JSON avec la structure suivante :
{
"timestamp": 1705431600000,
"webhookEvent": "sprint_started",
"sprint": {
"id": 15,
"self": "https://your-domain.atlassian.net/rest/agile/1.0/sprint/15",
"state": "active",
"name": "Sprint 12",
"startDate": "2026-02-02T00:00:00.000Z",
"endDate": "2026-02-27T00:00:00.000Z",
"originBoardId": 2,
"goal": "Complete payment processing improvements"
}
}
L’intergiciel utilise sprint.originBoardId pour rechercher l’ID du site Kinsta et sprint.name pour nommer le nouvel environnement : chaque évènement sprint_started dans votre instance Jira atteint le point de terminaison. La recherche de l’ID du tableau dans la carte de configuration est ce qui permet d’étendre l’automatisation au bon projet client et d’ignorer tout le reste.
2. Construire le point de terminaison de l’intergiciel
Avec le webhook en place, vous devez initialiser un nouveau projet Node.js et installer Express.js avec dotenv :
npm init -y
npm install express dotenv
express s’occupe du routage et de l’analyse des requêtes, tandis que dotenv charge votre fichier .env. Vous devez créer app.js pour configurer le serveur. Voici le fichier complet :
// app.js
const express = require('express');
const crypto = require('crypto');
require('dotenv').config();
const app = express();
// Raw body parser on the /sprint route enables HMAC signature verification
app.use('/sprint', express.raw({ type: 'application/json' }));
app.use(express.json());
const KinstaAPIUrl = 'https://api.kinsta.com/v2';
const headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.KINSTA_API_KEY}`
};
// Board ID to Kinsta site ID config map
const siteConfig = {
[process.env.BOARD_ID_CLIENT_A]: process.env.SITE_ID_CLIENT_A,
[process.env.BOARD_ID_CLIENT_B]: process.env.SITE_ID_CLIENT_B,
};
function verifyJiraSignature(req) {
const signature = req.headers['x-hub-signature'];
const secret = process.env.JIRA_WEBHOOK_SECRET;
if (!signature || !secret) return false;
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(req.body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
app.post('/sprint', async (req, res) => {
if (!verifyJiraSignature(req)) {
return res.status(401).json({ message: 'Invalid signature' });
}
const body = JSON.parse(req.body);
const { webhookEvent, sprint } = body;
if (webhookEvent !== 'sprint_started') {
return res.status(200).json({ message: 'Event ignored' });
}
const boardId = String(sprint.originBoardId);
const siteId = siteConfig[boardId];
if (!siteId) {
console.log(`No site configured for board ${boardId}`);
return res.status(200).json({ message: 'Board not mapped' });
}
// Kinsta API calls added in the steps below
res.status(200).json({ message: 'Received' });
});
app.listen(3000, () => console.log('Middleware running on port 3000'));
Pour protéger le point de terminaison, vous générez une clé secrète lors de la configuration du webhook. Jira rend cela facultatif pendant la configuration, mais c’est pratiquement essentiel pour une instance sécurisée.
Sécurité du point de terminaison
Jira signe chaque charge utile et inclut le résultat dans l’en-tête X-Hub-Signature sous la forme sha256=<hash>. Vous ajoutez le secret à votre fichier .env avec les autres informations d’identification :
JIRA_WEBHOOK_SECRET=your_webhook_secret_here
La fonction de vérification se trouve dans app.js et utilise le module cryptographique intégré de Node. Elle lit la signature dans l’en-tête de la requête, calcule le HMAC attendu par rapport au corps de la requête brute, et utilise timingSafeEqual pour les comparer de manière à empêcher les attaques temporelles. Voici la partie concernée du fichier app.js :
const crypto = require('crypto');
function verifyJiraSignature(req) {
const signature = req.headers['x-hub-signature'];
const secret = process.env.JIRA_WEBHOOK_SECRET;
if (!signature || !secret) return false;
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(req.body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Cette fonction est la première chose appelée dans le gestionnaire de route POST /sprint. Si la vérification échoue, l’intergiciel renvoie 401 immédiatement, et rien d’autre ne s’exécute :
app.post('/sprint', async (req, res) => {
if (!verifyJiraSignature(req)) {
return res.status(401).json({ message: 'Invalid signature' });
}
const body = JSON.parse(req.body);
// …rest of the handler
});
La route utilise express.raw() sur le chemin /sprint car verifyJiraSignature en a besoin pour calculer le HMAC. Une fois la vérification réussie, JSON.parse(req.body) donne le même résultat que express.json().
3. S’authentifier avec l’API Kinsta et récupérer les environnements du site
Toutes les requêtes à l’API Kinsta utilisent l’authentification par jeton Bearer : la constante headers dans app.js gère cela pour chaque requête dans l’application. La ligne require('dotenv').config() au sommet assure que la clé se charge à partir de .env avant que quoi que ce soit d’autre ne s’exécute, donc elle n’apparaît jamais dans le code source lui-même.
Kinsta utilise les ID d’environnement plutôt que les ID de site pour le point final de provisionnement, vous devez donc ajouter une fonction getEnvironmentId sous la constante headers :
const getEnvironmentId = async (siteId) => {
const resp = await fetch(
`${KinstaAPIUrl}/sites/${siteId}/environments`,
{ method: 'GET', headers }
);
const data = await resp.json();
return data.site.environments[0].id;
};
Cette méthode appelle GET /sites/{siteId}/environments et renvoie l’identifiant du premier environnement (c’est-à-dire en ligne) dans la réponse. Si un site utilise plusieurs environnements et que vous devez en cibler un spécifique, comparez avec le nom de l’environnement plutôt que de prendre le premier résultat.
4. Créer un environnement de staging simple à l’aide de l’API Kinsta
Une fois les identifiants du site et de l’environnement résolus, l’intergiciel appelle POST /sites/{siteId}/environments/plain pour créer l’environnement de sprint. Pour cela, vous utilisez la fonction createSprintEnvironment située sous getEnvironmentId :
const createSprintEnvironment = async (siteId, sprintName) => {
const resp = await fetch(
`${KinstaAPIUrl}/sites/${siteId}/environments/plain`,
{
method: 'POST',
headers,
body: JSON.stringify({
display_name: sprintName,
is_premium: false
})
}
);
const data = await resp.json();
return data;
};
display_name apparaît dans MyKinsta, alors que l’utilisation de sprint.name à partir du payload Jira directement signifie que chaque environnement dans le tableau de bord correspond au sprint auquel il appartient. Le drapeau is_premium détermine si Kinsta le provisionne comme un environnement de staging standard ou premium. En le définissant à false, vous créez un environnement standard.
Lorsque la requête atteint Kinsta, elle renvoie 202 Accepted avec un operation_id plutôt qu’un environnement complété :
{
"operation_id": "environments:add-plain-54fb80af-576c-4fdc-ba4f-b596c83f15a1",
"message": "Adding plain environment in progress",
"status": 202
}
Le traitement async de Kinsta évite de bloquer le fil de la requête pendant que le provisionnement se termine. L’identifiant de l'opération est ce que vous transmettez au point de terminaison pour suivre la progression. Ensuite, mettez à jour la route POST /sprint pour appeler les deux fonctions en séquence :
app.post('/sprint', async (req, res) => {
if (!verifyJiraSignature(req)) {
return res.status(401).json({ message: 'Invalid signature' });
}
const body = JSON.parse(req.body);
const { webhookEvent, sprint } = body;
if (webhookEvent !== 'sprint_started') {
return res.status(200).json({ message: 'Event ignored' });
}
const boardId = String(sprint.originBoardId);
const siteId = siteConfig[boardId];
if (!siteId) {
console.log(`No site configured for board ${boardId}`);
return res.status(200).json({ message: 'Board not mapped' });
}
try {
const envId = await getEnvironmentId(siteId);
const result = await createSprintEnvironment(siteId, sprint.name);
res.status(200).json(result);
} catch (err) {
console.error(err);
res.status(500).json({ message: 'Environment creation failed' });
}
});
L’utilisation du bloc try est plus propre que l’utilisation de plusieurs instructions if. Cependant, gardez la vérification de la signature Jira en tête du fichier car elle doit être exécutée avant tout autre code.
5. Interroger l’état de l’opération et confirmer le provisionnement
Pour suivre l’achèvement, interrogez GET /operations/{operation_id} jusqu’à ce que l’état revienne à 200 à l’aide d’une fonction pollOperation sous createSprintEnvironment :
const pollOperation = async (operationId, intervalMs = 5000, maxAttempts = 12) => {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
await new Promise(resolve => setTimeout(resolve, intervalMs));
const resp = await fetch(
`${KinstaAPIUrl}/operations/${operationId}`,
{ method: 'GET', headers }
);
const data = await resp.json();
if (data.status === 200) {
console.log(`Environment ready: ${operationId}`);
return data;
}
if (data.status >= 400) {
throw new Error(`Operation failed: ${data.message}`);
}
}
throw new Error('Operation timed out after maximum attempts');
};
La boucle attend cinq secondes entre chaque tentative et couvre jusqu’à une minute de temps de provisionnement. Si 200 signale l’achèvement de l’opération, tout état 4xx indique que l’enquête n’a pas abouti.

Si vous exécutez tout cela avec node app.js et démarrez un sprint dans Jira, l’environnement devrait apparaitre dans MyKinsta en l’espace d’une minute ou deux.
Gardez votre agence en avance sur le sprint
Cette intégration fournit un environnement de staging propre et nommé dans MyKinsta, basé sur le démarrage d’un sprint dans Jira. Le webhook se déclenche, le middleware résout l’ID du forum en un site, l’API Kinsta s’occupe du reste, et l’équipe récupère ses tickets avec un environnement qui l’attend déjà.
Lorsque l’intergiciel est prêt à être mis en service, Sevalla est une cible de déploiement simple. Vous poussez le projet vers un fournisseur Git, connectez le repo, ajoutez les variables d’environnement et mettez à jour l’URL du webhook Jira avec l’adresse live.
De plus, le programme Agency Partner de Kinsta est idéal pour les agences qui gèrent plusieurs projets clients. Il vous offre une assistance dédiée, des opportunités de co-marketing et le type de partenariat d’infrastructure qui prend en charge la couche d’automatisation que vous construisez au-dessus de l’API Kinsta.