L'API di Vimonto Deploy permette a script e pipeline CI di lavorare con le tue organizzazioni tramite HTTPS e JSON: elencare server e siti, avviare un deploy e seguirlo, creare e rimuovere database, eseguire backup e ricette. Ogni richiesta è autenticata con un token API personale che crei nel tuo account.
Un token agisce come te. Può fare solo ciò che il tuo ruolo consente, solo sui server a cui hai accesso e solo entro gli ambiti che gli hai assegnato.

Creare un token API
- Apri il menu account in alto a destra e scegli Impostazioni account → Token API.
- Fai clic su Nuovo token.
- Inserisci un Nome che indichi dove viene usato, per esempio "GitHub Actions".
- In Ambiti, seleziona cosa può fare il token (vedi sotto).
- In Scade, scegli Tra 30 giorni, Tra 90 giorni (il valore predefinito), Tra 365 giorni o Mai.
- Fai clic su Crea token.
Il token viene mostrato una sola volta, in Il tuo nuovo token. Fai clic su Copia e conservalo in un posto sicuro, come i secret della tua CI; Vimonto Deploy ne conserva solo un hash e non può mostrarlo di nuovo. Un token è fatto così: 12| seguito da una lunga stringa di lettere e cifre.
L'elenco mostra per ogni token il nome, quando è stato usato l'ultima volta, quando scade e i suoi ambiti. Fai clic su Revoca per eliminare un token: script e pipeline che lo usano smettono subito di funzionare. Eliminando il tuo account revochi tutti i tuoi token.
Ambiti
| Ambito | Valore | Consente |
|---|---|---|
| Lettura | read |
Vedere server, siti, deploy, database, backup, ricette e task. |
| Deploy | deploy |
Avviare deploy e seguirli: trovare un sito per dominio o ID, elencare e vedere i deploy e vedere i task. Pensato per le pipeline CI. |
| Scrittura | write |
Tutto ciò che consente Lettura, più avviare deploy, creare e rimuovere database ed eseguire backup e ricette. |
Un token con solo Deploy può cercare il sito di cui fa il deploy (vedi trovare un sito), ma non può elencare server o siti: dai a una pipeline CI solo questo ambito e usa Lettura o Scrittura per gli script che hanno bisogno di più.
L'ambito è il primo controllo. Il tuo ruolo è il secondo: avviare un deploy, modificare database ed eseguire backup o ricette richiedono il ruolo di proprietario, amministratore, manager o sviluppatore. Il token di un osservatore può leggere, ma ogni modifica viene rifiutata con 403.
URL di base e autenticazione
Tutti gli endpoint si trovano sotto /api/v1 all'indirizzo dove usi Vimonto Deploy. Negli esempi qui sotto è https://deploy.example.com/api/v1; sostituisci deploy.example.com con il tuo indirizzo.
Invia il token come bearer token nell'header Authorization e chiedi JSON:
curl https://deploy.example.com/api/v1/user \
-H "Authorization: Bearer $VIMONTO_TOKEN" \
-H "Accept: application/json"
Solo i token aprono l'API: aver effettuato l'accesso all'app nel browser non basta. I corpi delle richieste sono JSON (Content-Type: application/json). Le date sono in ISO 8601 con fuso orario. I messaggi nelle risposte, come gli errori, sono nella lingua impostata nel tuo account; se non ne hai scelta una, nella lingua dell'header Accept-Language della richiesta (inglese, olandese, tedesco, francese o italiano), altrimenti in inglese.
Organizzazioni, server e siti nell'URL
Gli endpoint di un'organizzazione iniziano con /orgs/{organization}, dove {organization} è lo slug dell'organizzazione: la prima parte del suo indirizzo nell'app (https://deploy.example.com/acme/… ha lo slug acme). GET /user elenca gli slug che il tuo token può raggiungere.
Server, siti e tutto ciò che sta sotto sono indicati con il loro ID numerico, lo stesso numero che compare nell'indirizzo dell'app: /acme/servers/12/sites/34 nell'app è /orgs/acme/servers/12/sites/34 nell'API. Un elemento figlio deve appartenere al suo genitore: il sito 34 sul server 12 funziona solo se il sito si trova su quel server, altrimenti l'API risponde 404.
Un'organizzazione di cui non sei membro, e un server a cui i tuoi team non ti danno accesso, rispondono 404, non 403.
Endpoint
| Metodo | Percorso | Ambiti |
|---|---|---|
GET |
/user |
qualsiasi |
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 token ha bisogno di uno degli ambiti indicati. I percorsi qui sotto omettono il prefisso https://deploy.example.com/api/v1.
Ottenere l'utente del token
GET /user restituisce a chi appartiene il token, il nome e gli ambiti del token e le organizzazioni che può raggiungere, con il tuo ruolo in ciascuna. Ogni ambito può chiamarlo, quindi è un buon primo test per un token.
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" }
]
}
}
Elencare i server
GET /orgs/{organization}/servers restituisce i server dell'organizzazione a cui hai accesso, in ordine di nome. GET /orgs/{organization}/servers/{server} restituisce un solo server.
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"
}
]
}
| Campo | Valori |
|---|---|
type |
app, web, worker, database, cache, meilisearch, loadbalancer |
status |
creating, waiting, provisioning, active, failed, disconnected, deleting |
provider |
Il provider cloud, oppure custom per un VPS personalizzato. |
database |
mysql-8.4, mysql-8.0, mariadb-11.4, mariadb-10.11, postgres-18, postgres-17, postgres-16, oppure null |
Segreti come password e chiavi non fanno mai parte di una risposta.
Elencare i siti
GET /orgs/{organization}/servers/{server}/sites restituisce i siti del server, in ordine di dominio. GET /orgs/{organization}/servers/{server}/sites/{site} restituisce un solo sito.
{
"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 è uno tra laravel, symfony, statamic, wordpress, phpmyadmin, php, nextjs, nuxt, html, other e loadbalancer. status è installed quando il sito è pronto; mentre cambia è installing, updating o removing, e failed quando qualcosa è andato storto. quick_deploy è il deploy a ogni push; isolated indica se il sito gira con un proprio utente Linux. Il file di ambiente del sito e l'URL di deploy non vengono mai restituiti.
Trovare un sito
GET /orgs/{organization}/sites restituisce i siti su tutti i server a cui hai accesso, in ordine di dominio, ciascuno con il suo server (ID e nome). Gli altri campi sono gli stessi visti sopra. Restringi l'elenco con i parametri della query:
| Parametro | Cerca per |
|---|---|
domain |
Il dominio del sito, senza distinguere maiuscole e minuscole. |
id |
L'ID del sito. |
server |
L'ID o il nome del server. |
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"
}
]
}
Anche un token con il solo ambito Deploy può chiamarlo, per trovare il sito di cui fa il deploy, ma deve indicare domain o id; senza, la risposta è 422. Se nulla corrisponde, data è un elenco vuoto.
Elencare i deploy
GET /orgs/{organization}/servers/{server}/sites/{site}/deployments restituisce i deploy del sito, dal più recente, 25 per pagina (vedi paginazione). GET …/deployments/{deployment} ne restituisce uno.
{
"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"
}
}
| Campo | Valori |
|---|---|
status |
queued, running, succeeded, failed, cancelled |
trigger |
manual, push, url (l'URL di deploy), rollback, api |
commit |
null finché il codice non è stato scaricato. |
release |
La directory della release, oppure live per un sito senza deploy zero-downtime; null finché il deploy non è iniziato. |
Avviare un deploy
POST /orgs/{organization}/servers/{server}/sites/{site}/deployments fa il deploy del branch del sito, esattamente come Fai il deploy nell'app. Non ha corpo. Risponde 202 Accepted con il nuovo deploy; seguilo tramite il suo 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"
}
}
409quando è già in corso un deploy del sito; iltask_idnella risposta è il task in corso.422quando il sito non è ancora pronto per il deploy o non ha un repository.
Vedi deploy per cosa fa un deploy.
Elencare e creare database
GET /orgs/{organization}/servers/{server}/databases restituisce i database del server, in ordine di nome.
{
"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 crea un database sul server. Il corpo ha un solo campo:
| Campo | Regole |
|---|---|
name |
Obbligatorio. Da 1 a 63 lettere, cifre e trattini bassi, unico sul server. |
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 risposta è 202: il database viene creato da un task sul server. Il suo status è installing, poi installed, oppure failed se il task non riesce. Il server deve essere attivo e avere un database installato, altrimenti la risposta è 422.
Eliminare un database
DELETE /orgs/{organization}/servers/{server}/databases/{database} elimina il database sul server. Risponde 202 con il database, ora removing, e il task che lo rimuove in task_id, dentro data come ogni endpoint che avvia un task:
{
"data": { "id": 4, "server_id": 12, "name": "shop_staging", "status": "removing", "created_at": "2026-10-07T15:10:00+00:00", "task_id": 9123 }
}
Vedi database.
Elencare i backup ed eseguirne uno
GET /orgs/{organization}/servers/{server}/backups restituisce le configurazioni di backup del server, in ordine di nome, ciascuna con i suoi 20 backup più recenti. size è in byte.
{
"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 è minute, hourly, nightly, weekly, monthly, reboot o custom; schedule è l'espressione cron. Lo status di un backup è running, succeeded o failed.
POST /orgs/{organization}/servers/{server}/backups/{backup}/run, con l'ID di una configurazione di backup, avvia subito un backup. Non ha corpo e risponde 202:
{ "data": { "backup_id": 141, "task_id": 9124 } }
409 quando è già in corso un backup di quella configurazione. Vedi backup.
Elencare le ricette ed eseguirne una
GET /orgs/{organization}/recipes restituisce le ricette dell'organizzazione, in ordine di nome. run_as è root o 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 esegue una ricetta su uno o più server.
| Campo | Regole |
|---|---|
servers |
Obbligatorio. Un elenco di ID di server, almeno uno. |
notify |
Facoltativo, true o false (predefinito). Con true ricevi un report via email quando tutti i server hanno finito. |
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 }
]
}
}
Ogni server che indichi deve esistere, esserti accessibile ed essere attivo. Altrimenti la ricetta non viene eseguita da nessuna parte e la risposta è 422: errors.servers elenca gli ID dei server che non esistono o a cui non hai accesso, oppure i nomi dei server non attivi. La risposta elenca ogni server con il proprio task. Vedi ricette.
Seguire un task
Il lavoro lungo (un deploy, un database, un backup, una ricetta su un server) gira come task in background, lo stesso che vedi in attività. GET /orgs/{organization}/tasks/{task} ne restituisce lo stato e l'output:
{
"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 è queued, running, succeeded, failed o cancelled; gli ultimi tre sono definitivi. progress va da 0 a 100. Quando un task non riesce, error spiega perché. Interroga l'endpoint ogni pochi secondi finché lo stato non è definitivo.
Paginazione
Solo l'elenco dei deploy è paginato, con 25 deploy per pagina, dal più recente. Chiedi un'altra pagina con ?page=2. La risposta contiene links e meta accanto a 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 contiene anche un elenco links per i pulsanti delle pagine. Segui links.next finché non è null. Tutti gli altri elenchi restituiscono tutto in una sola risposta.
Errori
Gli errori sono JSON con un message:
{ "message": "shop.example.com is not ready to deploy yet." }
| Stato | Significato |
|---|---|
401 |
Nessun token, un token sbagliato o revocato, oppure scaduto: {"message": "Unauthenticated."} |
403 |
Al token manca l'ambito ("Invalid ability provided."), oppure il tuo ruolo non consente la modifica ("Your role does not allow this."). |
404 |
L'organizzazione, il server, il sito o un altro elemento non esiste, oppure non hai accesso. Non fare affidamento sul message. |
409 |
Lo stesso lavoro è già in corso. La risposta contiene il task_id del task in corso. |
422 |
La richiesta non si può eseguire: campi non validi, oppure un motivo come un server non ancora pronto. |
429 |
Troppe richieste; vedi limiti di frequenza. |
Un 409 è fatto così:
{ "message": "Deploying to shop.example.com is already running.", "task_id": 9121 }
Un 422 per campi non validi li elenca in errors:
{
"message": "The name field format is invalid.",
"errors": {
"name": ["The name field format is invalid."]
}
}
Limiti di frequenza
Ogni token può fare 120 richieste al minuto. Ogni risposta ha gli header X-RateLimit-Limit e X-RateLimit-Remaining. Oltre il limite, l'API risponde 429 con un header Retry-After: il numero di secondi da attendere.
Quando interroghi un task, una volta ogni pochi secondi è più che sufficiente.
Deploy da GitHub Actions
Questo workflow fa il deploy dopo che i test sono passati e fallisce quando il deploy non riesce. Crea un token con solo l'ambito Deploy e aggiungilo ai secret del repository come VIMONTO_TOKEN (Settings → Secrets and variables → Actions su GitHub). Inserisci il tuo indirizzo, lo slug dell'organizzazione, l'ID del server e l'ID del sito.
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
# needs: tests # deploy solo dopo che il job dei test è passato
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")
# Avvia il deploy; curl fallisce con 4xx/5xx, per esempio 409 se ne è già in corso uno.
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"
# Segui il task finché non è terminato.
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
Disattiva Deploy a ogni push per il sito quando è la CI a fare il deploy. Altrimenti un push avvia già da solo un deploy, e la richiesta della pipeline riceve 409 perché un deploy è già in corso.
Oppure usa la CLI
La CLI di Vimonto Deploy racchiude queste richieste in un solo comando: deploy deploy shop.example.com --watch avvia il deploy, segue il task ed esce con il suo risultato. Nella CI legge il token da DEPLOY_TOKEN.
Oppure usa l'URL di deploy
Se ti basta avviare un deploy, l'URL di deploy segreto del sito è più semplice: un solo POST senza token e niente da seguire. Però non dice alla tua pipeline se il deploy è riuscito. Vedi deploy.
Domande frequenti
Un token è legato a una sola organizzazione?
No. Un token raggiunge ogni organizzazione di cui sei membro, con il tuo ruolo in ciascuna. GET /user le elenca. Crea un account separato se una pipeline deve raggiungere una sola organizzazione.
Cosa succede ai miei token quando cambia il mio ruolo?
Un token segue sempre il tuo ruolo attuale e il tuo accesso ai server. Quando perdi un permesso o lasci un'organizzazione, anche il token lo perde, subito.
Posso creare server o siti tramite l'API?
Non ancora. L'API copre la lettura di server, siti, deploy, database, backup, ricette e task; il deploy; la creazione e la rimozione di database; e l'esecuzione di backup e ricette.
Dove trovo l'ID del server e del sito?
Nella barra degli indirizzi dell'app: nelle pagine di un sito l'indirizzo è /{organization}/servers/{server}/sites/{site}/…. Anche GET /orgs/{organization}/servers e GET …/servers/{server}/sites li elencano, e GET /orgs/{organization}/sites?domain=shop.example.com trova un sito con l'ID del suo server a partire dal dominio.