L’API de Vimonto Deploy permet aux scripts et aux pipelines CI de travailler avec vos organisations en HTTPS et JSON : lister les serveurs et les sites, lancer un déploiement et le suivre, créer et supprimer des bases de données, exécuter des sauvegardes et des recettes. Chaque requête est authentifiée par un jeton d’API personnel que vous créez dans votre compte.
Un jeton agit en votre nom. Il ne peut faire que ce que votre rôle permet, uniquement sur les serveurs auxquels vous avez accès, et uniquement dans les portées que vous lui avez données.

Créer un jeton d’API
- Ouvrez le menu du compte en haut à droite et choisissez Paramètres du compte → Jetons d’API.
- Cliquez sur Nouveau jeton.
- Saisissez un Nom qui indique où il est utilisé, par exemple « GitHub Actions ».
- Sous Portées, cochez ce que le jeton peut faire (voir ci-dessous).
- Sous Expire, choisissez Dans 30 jours, Dans 90 jours (par défaut), Dans 365 jours ou Jamais.
- Cliquez sur Créer le jeton.
Le jeton n'est affiché qu'une fois, sous Ton nouveau jeton. Cliquez sur Copier et conservez-le en lieu sûr, par exemple dans les secrets de votre CI ; Vimonto Deploy n'en garde qu'une empreinte (hash) et ne peut plus l'afficher. Un jeton ressemble à 12| suivi d'une longue suite de lettres et de chiffres.
La liste affiche pour chaque jeton son nom, sa dernière utilisation, sa date d'expiration et ses portées. Cliquez sur Révoquer pour supprimer un jeton : les scripts et pipelines qui l'utilisent cessent aussitôt de fonctionner. Supprimer votre compte révoque tous vos jetons.
Portées
| Portée | Valeur | Permet |
|---|---|---|
| Lecture | read |
Voir les serveurs, sites, déploiements, bases de données, sauvegardes, recettes et tâches. |
| Déployer | deploy |
Lancer des déploiements et les suivre : trouver un site par domaine ou identifiant, lister et voir les déploiements et voir les tâches. Pensé pour les pipelines CI. |
| Écriture | write |
Tout ce que permet Lecture, plus lancer des déploiements, créer et supprimer des bases de données, et exécuter des sauvegardes et des recettes. |
Un jeton avec seulement Déployer peut retrouver le site qu'il déploie (voir trouver un site), mais ne peut pas lister les serveurs ni les sites : donnez à un pipeline CI uniquement cette portée, et utilisez Lecture ou Écriture pour les scripts qui ont besoin de plus.
La portée est le premier contrôle. Votre rôle est le second : lancer un déploiement, modifier des bases de données et exécuter des sauvegardes ou des recettes nécessite le rôle de propriétaire, d'administrateur, de manager ou de développeur. Le jeton d'un lecteur peut lire, mais chaque modification est refusée avec 403.
URL de base et authentification
Tous les endpoints se trouvent sous /api/v1 à l'adresse où vous utilisez Vimonto Deploy. Dans les exemples ci-dessous, c'est https://deploy.example.com/api/v1 ; remplacez deploy.example.com par votre propre adresse.
Envoyez le jeton comme jeton bearer dans l'en-tête Authorization, et demandez du JSON :
curl https://deploy.example.com/api/v1/user \
-H "Authorization: Bearer $VIMONTO_TOKEN" \
-H "Accept: application/json"
Seuls les jetons ouvrent l’API : être connecté à l'application dans votre navigateur ne suffit pas. Les corps de requête sont en JSON (Content-Type: application/json). Les dates sont au format ISO 8601 avec un fuseau horaire. Les messages des réponses, comme les erreurs, sont dans la langue choisie dans votre compte ; si vous n'en avez pas choisi, dans la langue de l'en-tête Accept-Language de la requête (anglais, néerlandais, allemand, français ou italien), sinon en anglais.
Organisations, serveurs et sites dans l'URL
Les endpoints d'organisation commencent par /orgs/{organization}, où {organization} est le slug de l'organisation : la première partie de son adresse dans l'application (https://deploy.example.com/acme/… a le slug acme). GET /user liste les slugs que votre jeton peut atteindre.
Les serveurs, les sites et tout ce qui se trouve en dessous sont désignés par leur identifiant numérique, le même nombre que dans l'adresse de l'application : /acme/servers/12/sites/34 dans l'application devient /orgs/acme/servers/12/sites/34 dans l’API. Un élément enfant doit appartenir à son parent : le site 34 sur le serveur 12 ne fonctionne que si le site est sur ce serveur, sinon l’API répond 404.
Une organisation dont vous n'êtes pas membre, et un serveur auquel vos équipes ne vous donnent pas accès, répondent 404, pas 403.
Endpoints
| Méthode | Chemin | Portées |
|---|---|---|
GET |
/user |
toutes |
GET |
/orgs/{organization}/servers |
read, write |
GET |
/orgs/{organization}/servers/{server} |
read, write |
GET |
/orgs/{organization}/servers/{server}/sites |
read, write |
GET |
/orgs/{organization}/servers/{server}/sites/{site} |
read, write |
GET |
/orgs/{organization}/sites |
read, deploy, write |
GET |
/orgs/{organization}/servers/{server}/sites/{site}/deployments |
read, deploy, write |
GET |
/orgs/{organization}/servers/{server}/sites/{site}/deployments/{deployment} |
read, deploy, write |
POST |
/orgs/{organization}/servers/{server}/sites/{site}/deployments |
deploy, write |
GET |
/orgs/{organization}/servers/{server}/databases |
read, write |
POST |
/orgs/{organization}/servers/{server}/databases |
write |
DELETE |
/orgs/{organization}/servers/{server}/databases/{database} |
write |
GET |
/orgs/{organization}/servers/{server}/backups |
read, write |
POST |
/orgs/{organization}/servers/{server}/backups/{backup}/run |
write |
GET |
/orgs/{organization}/recipes |
read, write |
POST |
/orgs/{organization}/recipes/{recipe}/run |
write |
GET |
/orgs/{organization}/tasks/{task} |
read, deploy, write |
Un jeton a besoin de l'une des portées indiquées. Les chemins ci-dessous omettent le préfixe https://deploy.example.com/api/v1.
Obtenir l'utilisateur du jeton
GET /user renvoie à qui appartient le jeton, le nom et les portées du jeton, et les organisations qu'il peut atteindre avec votre rôle dans chacune. Toutes les portées peuvent l'appeler : c'est un bon premier test pour un jeton.
curl https://deploy.example.com/api/v1/user \
-H "Authorization: Bearer $VIMONTO_TOKEN" -H "Accept: application/json"
{
"data": {
"id": 7,
"name": "Sam de Vries",
"email": "sam@example.com",
"token": {
"name": "GitHub Actions",
"scopes": ["deploy"]
},
"organizations": [
{ "slug": "acme", "name": "Acme", "role": "developer" }
]
}
}
Lister les serveurs
GET /orgs/{organization}/servers renvoie les serveurs de l'organisation auxquels vous avez accès, triés par nom. GET /orgs/{organization}/servers/{server} renvoie un seul serveur.
curl https://deploy.example.com/api/v1/orgs/acme/servers \
-H "Authorization: Bearer $VIMONTO_TOKEN" -H "Accept: application/json"
{
"data": [
{
"id": 12,
"name": "web-1",
"type": "app",
"status": "active",
"provider": "hetzner",
"region": "fsn1",
"size": "cx32",
"ip_address": "203.0.113.10",
"private_ip_address": "10.0.0.2",
"ssh_port": 22,
"user": "vimonto",
"php_version": "8.4",
"database": "mysql-8.4",
"ubuntu_version": "24.04",
"timezone": "UTC",
"tags": ["production"],
"created_at": "2026-09-01T09:30:00+00:00"
}
]
}
| Champ | Valeurs |
|---|---|
type |
app, web, worker, database, cache, meilisearch, loadbalancer |
status |
creating, waiting, provisioning, active, failed, disconnected, deleting |
provider |
Le fournisseur cloud, ou custom pour un VPS personnalisé. |
database |
mysql-8.4, mysql-8.0, mariadb-11.4, mariadb-10.11, postgres-18, postgres-17, postgres-16, ou null |
Les secrets tels que les mots de passe et les clés ne font jamais partie d'une réponse.
Lister les sites
GET /orgs/{organization}/servers/{server}/sites renvoie les sites du serveur, triés par domaine. GET /orgs/{organization}/servers/{server}/sites/{site} renvoie un seul site.
{
"data": {
"id": 34,
"server_id": 12,
"domain": "shop.example.com",
"aliases": ["www.shop.example.com"],
"preview_domain": "kalme-rivier-4821.on-deploy.link",
"framework": "laravel",
"status": "installed",
"php_version": "8.4",
"repository": "acme/shop",
"branch": "main",
"quick_deploy": true,
"zero_downtime": true,
"isolated": false,
"current_release": "20261007143012",
"deployed_at": "2026-10-07T14:31:40+00:00",
"created_at": "2026-09-01T10:02:11+00:00"
}
}
framework vaut laravel, symfony, statamic, wordpress, phpmyadmin, php, nextjs, nuxt, html, other ou loadbalancer. status vaut installed quand le site est prêt ; pendant une modification, il vaut installing, updating ou removing, et failed en cas d'échec. quick_deploy correspond au déploiement à chaque push ; isolated indique si le site tourne sous son propre utilisateur Linux. Le fichier d'environnement du site et son URL de déploiement ne sont jamais renvoyés.
Trouver un site
GET /orgs/{organization}/sites renvoie les sites de tous les serveurs auxquels vous avez accès, triés par domaine, chacun avec son server (identifiant et nom). Les autres champs sont les mêmes que ci-dessus. Affinez la liste avec des paramètres de requête :
| Paramètre | Correspond à |
|---|---|
domain |
Le domaine du site, sans tenir compte de la casse. |
id |
L'identifiant du site. |
server |
L'identifiant ou le nom du serveur. |
curl "https://deploy.example.com/api/v1/orgs/acme/sites?domain=shop.example.com" \
-H "Authorization: Bearer $VIMONTO_TOKEN" -H "Accept: application/json"
{
"data": [
{
"id": 34,
"server_id": 12,
"server": { "id": 12, "name": "web-1" },
"domain": "shop.example.com",
"status": "installed",
"branch": "main"
}
]
}
Un jeton avec uniquement la portée Déployer peut aussi l'appeler, pour trouver le site qu'il déploie, mais doit alors passer domain ou id ; sans l'un des deux, la réponse est 422. Si rien ne correspond, data est une liste vide.
Lister les déploiements
GET /orgs/{organization}/servers/{server}/sites/{site}/deployments renvoie les déploiements du site, les plus récents en premier, 25 par page (voir pagination). GET …/deployments/{deployment} en renvoie un seul.
{
"data": {
"id": 581,
"site_id": 34,
"status": "succeeded",
"trigger": "api",
"branch": "main",
"commit": {
"hash": "9f2c4e1a7b3d5f60812a9c4e7d1b3a5c7e9f1a2b",
"author": "Sam de Vries",
"message": "Add checkout page"
},
"release": "20261007143012",
"task_id": 9120,
"started_at": "2026-10-07T14:30:12+00:00",
"finished_at": "2026-10-07T14:31:40+00:00",
"created_at": "2026-10-07T14:30:11+00:00"
}
}
| Champ | Valeurs |
|---|---|
status |
queued, running, succeeded, failed, cancelled |
trigger |
manual, push, url (l'URL de déploiement), rollback, api |
commit |
null tant que le code n'a pas été récupéré. |
release |
Le répertoire de la release, ou live pour un site sans déploiement sans interruption ; null tant que le déploiement n'a pas commencé. |
Lancer un déploiement
POST /orgs/{organization}/servers/{server}/sites/{site}/deployments déploie la branche du site, exactement comme Déployer maintenant dans l'application. Il ne prend pas de corps. Il répond 202 Accepted avec le nouveau déploiement ; suivez-le avec son task_id.
curl -X POST https://deploy.example.com/api/v1/orgs/acme/servers/12/sites/34/deployments \
-H "Authorization: Bearer $VIMONTO_TOKEN" -H "Accept: application/json"
{
"data": {
"id": 582,
"site_id": 34,
"status": "queued",
"trigger": "api",
"branch": "main",
"commit": null,
"release": null,
"task_id": 9121,
"started_at": null,
"finished_at": null,
"created_at": "2026-10-07T15:02:45+00:00"
}
}
409quand un déploiement du site est déjà en cours ; letask_idde la réponse est la tâche en cours.422quand le site n'est pas encore prêt à être déployé ou n'a pas de dépôt.
Consultez les déploiements pour savoir ce que fait un déploiement.
Lister et créer des bases de données
GET /orgs/{organization}/servers/{server}/databases renvoie les bases de données du serveur, triées par nom.
{
"data": [
{ "id": 3, "server_id": 12, "name": "shop", "status": "installed", "created_at": "2026-09-01T10:05:00+00:00" }
]
}
POST /orgs/{organization}/servers/{server}/databases crée une base de données sur le serveur. Le corps a un seul champ :
| Champ | Règles |
|---|---|
name |
Obligatoire. 1 à 63 lettres, chiffres et tirets bas, unique sur le serveur. |
curl -X POST https://deploy.example.com/api/v1/orgs/acme/servers/12/databases \
-H "Authorization: Bearer $VIMONTO_TOKEN" -H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name": "shop_staging"}'
{
"data": { "id": 4, "server_id": 12, "name": "shop_staging", "status": "installing", "created_at": "2026-10-07T15:10:00+00:00", "task_id": 9122 }
}
La réponse est 202 : la base de données est créée par une tâche sur le serveur. Son status vaut installing, puis installed, ou failed si la tâche échoue. Le serveur doit être actif et avoir une base de données installée, sinon la réponse est 422.
Supprimer une base de données
DELETE /orgs/{organization}/servers/{server}/databases/{database} supprime la base de données sur le serveur. Il répond 202 avec la base de données, désormais removing, et la tâche qui la retire dans task_id, à l'intérieur de data comme pour chaque endpoint qui lance une tâche :
{
"data": { "id": 4, "server_id": 12, "name": "shop_staging", "status": "removing", "created_at": "2026-10-07T15:10:00+00:00", "task_id": 9123 }
}
Consultez les bases de données.
Lister les sauvegardes et en lancer une
GET /orgs/{organization}/servers/{server}/backups renvoie les configurations de sauvegarde du serveur, triées par nom, chacune avec ses 20 dernières sauvegardes. size est en octets.
{
"data": [
{
"id": 2,
"name": "Nightly",
"databases": ["shop"],
"frequency": "nightly",
"schedule": "0 0 * * *",
"retention": 7,
"storage": "Backups bucket",
"backups": [
{
"id": 140,
"status": "succeeded",
"size": 48213504,
"databases": ["shop"],
"task_id": 9050,
"created_at": "2026-10-07T00:00:02+00:00",
"finished_at": "2026-10-07T00:01:15+00:00"
}
]
}
]
}
frequency vaut minute, hourly, nightly, weekly, monthly, reboot ou custom ; schedule est l'expression cron. Le status d'une sauvegarde vaut running, succeeded ou failed.
POST /orgs/{organization}/servers/{server}/backups/{backup}/run, avec l'identifiant d'une configuration de sauvegarde, lance une sauvegarde immédiatement. Il ne prend pas de corps et répond 202 :
{ "data": { "backup_id": 141, "task_id": 9124 } }
409 quand une sauvegarde de cette configuration est déjà en cours. Consultez les sauvegardes.
Lister les recettes et en exécuter une
GET /orgs/{organization}/recipes renvoie les recettes de l'organisation, triées par nom. run_as vaut root ou server_user.
{
"data": [
{ "id": 5, "name": "Install htop", "run_as": "root", "script": "apt-get install -y htop", "updated_at": "2026-09-20T08:12:00+00:00" }
]
}
POST /orgs/{organization}/recipes/{recipe}/run exécute une recette sur un ou plusieurs serveurs.
| Champ | Règles |
|---|---|
servers |
Obligatoire. Une liste d'identifiants de serveurs, au moins un. |
notify |
Facultatif, true ou false (par défaut). true vous envoie un rapport par e-mail quand tous les serveurs ont terminé. |
curl -X POST https://deploy.example.com/api/v1/orgs/acme/recipes/5/run \
-H "Authorization: Bearer $VIMONTO_TOKEN" -H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"servers": [12, 13], "notify": false}'
{
"data": {
"run_id": 77,
"servers": [
{ "server_id": 12, "task_id": 9125 },
{ "server_id": 13, "task_id": 9126 }
]
}
}
Chaque serveur indiqué doit exister, vous être accessible et être actif. Sinon, la recette ne s'exécute nulle part et la réponse est 422 : errors.servers liste les identifiants des serveurs qui n'existent pas ou auxquels vous n'avez pas accès, ou nomme les serveurs qui ne sont pas actifs. La réponse liste chaque serveur avec sa propre tâche. Consultez les recettes.
Suivre une tâche
Les travaux longs (un déploiement, une base de données, une sauvegarde, une recette sur un serveur) s'exécutent comme une tâche en arrière-plan, la même que celle que vous voyez dans l'activité. GET /orgs/{organization}/tasks/{task} renvoie son état et sa sortie :
{
"data": {
"id": 9121,
"type": "site.deploy",
"name": "Deploying to shop.example.com",
"status": "running",
"step": "Run deploy script",
"progress": 30,
"error": null,
"server_id": 12,
"output": "Cloning into 'releases/20261007150246'...\n",
"started_at": "2026-10-07T15:02:46+00:00",
"finished_at": null,
"created_at": "2026-10-07T15:02:45+00:00"
}
}
status vaut queued, running, succeeded, failed ou cancelled ; les trois derniers sont définitifs. progress va de 0 à 100. Quand une tâche échoue, error en donne la raison. Interrogez la tâche toutes les quelques secondes jusqu'à ce que le statut soit définitif.
Pagination
Seule la liste des déploiements est paginée, avec 25 déploiements par page, les plus récents en premier. Demandez une autre page avec ?page=2. La réponse contient links et meta à côté de data :
{
"data": [ … ],
"links": {
"first": "https://deploy.example.com/api/v1/orgs/acme/servers/12/sites/34/deployments?page=1",
"last": "https://deploy.example.com/api/v1/orgs/acme/servers/12/sites/34/deployments?page=4",
"prev": null,
"next": "https://deploy.example.com/api/v1/orgs/acme/servers/12/sites/34/deployments?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 4,
"path": "https://deploy.example.com/api/v1/orgs/acme/servers/12/sites/34/deployments",
"per_page": 25,
"to": 25,
"total": 92
}
}
meta contient aussi une liste links pour des boutons de page. Suivez links.next jusqu'à ce qu'il vaille null. Toutes les autres listes renvoient tout en une seule réponse.
Erreurs
Les erreurs sont du JSON avec un message :
{ "message": "shop.example.com is not ready to deploy yet." }
| Statut | Signification |
|---|---|
401 |
Pas de jeton, un jeton erroné ou révoqué, ou un jeton expiré : {"message": "Unauthenticated."} |
403 |
Le jeton n'a pas la portée ("Invalid ability provided."), ou votre rôle ne permet pas la modification ("Your role does not allow this."). |
404 |
L'organisation, le serveur, le site ou un autre élément n'existe pas, ou vous n'y avez pas accès. Ne vous fiez pas au message. |
409 |
Le même travail est déjà en cours. La réponse contient le task_id de la tâche en cours. |
422 |
La requête ne peut pas être traitée : champs invalides, ou une raison comme un serveur pas encore prêt. |
429 |
Trop de requêtes ; voir limites de requêtes. |
Un 409 ressemble à ceci :
{ "message": "Deploying to shop.example.com is already running.", "task_id": 9121 }
Un 422 pour des champs invalides les liste sous errors :
{
"message": "The name field format is invalid.",
"errors": {
"name": ["The name field format is invalid."]
}
}
Limites de requêtes
Chaque jeton peut faire 120 requêtes par minute. Chaque réponse contient les en-têtes X-RateLimit-Limit et X-RateLimit-Remaining. Au-delà de la limite, l’API répond 429 avec un en-tête Retry-After : le nombre de secondes à attendre.
Quand vous suivez une tâche, une requête toutes les quelques secondes suffit largement.
Déployer depuis GitHub Actions
Ce workflow déploie une fois les tests réussis et échoue quand le déploiement échoue. Créez un jeton avec uniquement la portée Déployer et ajoutez-le aux secrets du dépôt sous le nom VIMONTO_TOKEN (Settings → Secrets and variables → Actions sur GitHub). Renseignez votre propre adresse, le slug de l'organisation, l'identifiant du serveur et celui du site.
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
# needs: tests # ne déployer qu'après la réussite de votre job de tests
steps:
- name: Deploy to production
env:
VIMONTO_TOKEN: ${{ secrets.VIMONTO_TOKEN }}
API: https://deploy.example.com/api/v1/orgs/acme
SERVER: 12
SITE: 34
run: |
set -euo pipefail
auth=(-H "Authorization: Bearer $VIMONTO_TOKEN" -H "Accept: application/json")
# Lancer le déploiement ; curl échoue sur 4xx/5xx, par exemple 409 si un déploiement est déjà en cours.
task=$(curl -sS --fail-with-body -X POST "${auth[@]}" \
"$API/servers/$SERVER/sites/$SITE/deployments" | jq -r '.data.task_id')
echo "Deploy started, task $task"
# Suivre la tâche jusqu'à la fin.
while true; do
sleep 5
response=$(curl -sS --fail-with-body "${auth[@]}" "$API/tasks/$task")
status=$(echo "$response" | jq -r '.data.status')
echo "Status: $status ($(echo "$response" | jq -r '.data.step // ""'))"
case "$status" in
succeeded) exit 0 ;;
failed|cancelled)
echo "$response" | jq -r '.data.error // "", .data.output'
exit 1 ;;
esac
done
Désactivez Déployer à chaque push pour le site quand la CI le déploie. Sinon, un push lance déjà un déploiement de lui-même, et la requête du pipeline reçoit alors 409 parce qu'un déploiement est déjà en cours.
Ou utilisez la CLI
La CLI de Vimonto Deploy regroupe ces requêtes en une seule commande : deploy deploy shop.example.com --watch lance le déploiement, suit la tâche et se termine avec son résultat. En CI, elle lit le jeton dans DEPLOY_TOKEN.
Ou utilisez l'URL de déploiement
Quand vous avez seulement besoin de lancer un déploiement, l'URL de déploiement secrète du site est plus simple : un seul POST sans jeton, et rien à suivre. Elle n'indique pas à votre pipeline si le déploiement a réussi. Consultez les déploiements.
Questions fréquentes
Un jeton est-il lié à une seule organisation ?
Non. Un jeton atteint toutes les organisations dont vous êtes membre, avec votre rôle dans chacune. GET /user les liste. Créez un compte distinct si un pipeline ne doit atteindre qu'une seule organisation.
Que deviennent mes jetons quand mon rôle change ?
Un jeton suit toujours votre rôle et votre accès aux serveurs actuels. Quand vous perdez une autorisation ou quittez une organisation, le jeton la perd aussi, immédiatement.
Puis-je créer des serveurs ou des sites via l’API ?
Pas encore. L’API permet de lire les serveurs, sites, déploiements, bases de données, sauvegardes, recettes et tâches ; de déployer ; de créer et supprimer des bases de données ; et d'exécuter des sauvegardes et des recettes.
Où trouver l'identifiant du serveur et du site ?
Dans la barre d'adresse de l'application : sur les pages d'un site, l'adresse est /{organization}/servers/{server}/sites/{site}/…. GET /orgs/{organization}/servers et GET …/servers/{server}/sites les listent aussi, et GET /orgs/{organization}/sites?domain=shop.example.com trouve un site et l'identifiant de son serveur à partir de son domaine.