Naar de inhoud
Deploy
Blader door de documentatie

REST API: deployen vanuit CI en je servers automatiseren

Naslag voor de REST API van Vimonto Deploy: API-tokens en scopes, elk endpoint met voorbeelden, taken, fouten, rate limits en een deploy met GitHub Actions.

Bekijk als Markdown Bijgewerkt op 7 oktober 2026

Met de API van Vimonto Deploy werken scripts en CI-pipelines met je organisaties via HTTPS en JSON: servers en sites opvragen, een deploy starten en volgen, databases aanmaken en verwijderen, back-ups en recepten uitvoeren. Elk verzoek wordt geauthenticeerd met een persoonlijk API-token dat je in je account maakt.

Een token handelt als jou. Het kan alleen wat je rol toestaat, alleen op de servers waar je toegang toe hebt, en alleen binnen de scopes die je het gaf.

De pagina API-tokens met een lijst tokens en hun scopes
API-tokens in je account

Een API-token maken

  1. Open het accountmenu rechtsboven en kies Accountinstellingen → API-tokens.
  2. Klik op Nieuw token.
  3. Vul een Naam in die zegt waar het token gebruikt wordt, zoals "GitHub Actions".
  4. Vink onder Scopes aan wat het token mag doen (zie hieronder).
  5. Kies onder Verloopt Over 30 dagen, Over 90 dagen (de standaard), Over 365 dagen of Nooit.
  6. Klik op Token maken.

Het token wordt één keer getoond, onder Je nieuwe token. Klik op Kopiëren en bewaar het op een veilige plek, zoals de secrets van je CI; Vimonto Deploy bewaart alleen een hash en kan het niet opnieuw tonen. Een token ziet eruit als 12| gevolgd door een lange reeks letters en cijfers.

De lijst toont van elk token de naam, wanneer het voor het laatst is gebruikt, wanneer het verloopt en de scopes. Klik op Intrekken om een token te verwijderen: scripts en pipelines die het gebruiken werken meteen niet meer. Als je je account verwijdert, worden al je tokens ingetrokken.

Scopes

Scope Waarde Staat toe
Lezen read Servers, sites, deployments, databases, back-ups, recepten en taken bekijken.
Deploy deploy Deployments starten en volgen: een site op domein of ID opzoeken, deployments opvragen en bekijken en taken bekijken. Bedoeld voor CI-pipelines.
Schrijven write Alles wat Lezen toestaat, plus deployments starten, databases aanmaken en verwijderen, en back-ups en recepten uitvoeren.

Een token met alleen Deploy kan de site opzoeken die hij deployt (zie een site zoeken), maar geen servers of sites opvragen: geef een CI-pipeline alleen die scope, en gebruik Lezen of Schrijven voor scripts die meer nodig hebben.

De scope is de eerste controle. Je rol is de tweede: een deploy starten, databases wijzigen en back-ups of recepten uitvoeren vraagt de rol eigenaar, beheerder, manager of developer. Het token van een kijker kan lezen, maar elke wijziging wordt geweigerd met 403.

Basis-URL en authenticatie

Alle endpoints staan onder /api/v1 op het adres waar je Vimonto Deploy gebruikt. In de voorbeelden hieronder is dat https://deploy.example.com/api/v1; vervang deploy.example.com door je eigen adres.

Stuur het token als bearer token in de header Authorization, en vraag om JSON:

curl https://deploy.example.com/api/v1/user \
  -H "Authorization: Bearer $VIMONTO_TOKEN" \
  -H "Accept: application/json"

Alleen tokens geven toegang tot de API: ingelogd zijn in de app in je browser niet. Request bodies zijn JSON (Content-Type: application/json). Datums zijn ISO 8601 met een tijdzone. Berichten in antwoorden, zoals foutmeldingen, zijn in de taal die je in je account hebt ingesteld; heb je er geen gekozen, dan in de taal uit de Accept-Language-header van het request (Engels, Nederlands, Duits, Frans of Italiaans), en anders in het Engels.

Organisaties, servers en sites in de URL

Endpoints van een organisatie beginnen met /orgs/{organization}, waarbij {organization} de slug van de organisatie is: het eerste deel van haar adres in de app (https://deploy.example.com/acme/… heeft de slug acme). GET /user toont de slugs die je token kan bereiken.

Servers, sites en alles daaronder adresseer je met hun numerieke ID, hetzelfde getal als in het adres van de app: /acme/servers/12/sites/34 in de app is /orgs/acme/servers/12/sites/34 in de API. Een onderdeel moet bij zijn bovenliggende item horen: site 34 op server 12 werkt alleen als de site op die server staat, anders antwoordt de API 404.

Een organisatie waar je geen lid van bent, en een server waar je teams je geen toegang toe geven, antwoorden 404, niet 403.

Endpoints

Methode Pad Scopes
GET /user elke
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

Een token heeft een van de genoemde scopes nodig. De paden hieronder laten het voorvoegsel https://deploy.example.com/api/v1 weg.

De gebruiker van het token opvragen

GET /user geeft terug van wie het token is, de naam en scopes van het token, en de organisaties die het kan bereiken met je rol in elk. Elke scope mag het aanroepen, dus het is een goede eerste test van een 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" }
    ]
  }
}

Servers opvragen

GET /orgs/{organization}/servers geeft de servers van de organisatie waar je toegang toe hebt, gesorteerd op naam. GET /orgs/{organization}/servers/{server} geeft één 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"
    }
  ]
}
Veld Waarden
type app, web, worker, database, cache, meilisearch, loadbalancer
status creating, waiting, provisioning, active, failed, disconnected, deleting
provider De cloudprovider, of custom voor een eigen VPS.
database mysql-8.4, mysql-8.0, mariadb-11.4, mariadb-10.11, postgres-18, postgres-17, postgres-16, of null

Geheimen zoals wachtwoorden en sleutels zitten nooit in een antwoord.

Sites opvragen

GET /orgs/{organization}/servers/{server}/sites geeft de sites van de server, gesorteerd op domein. GET /orgs/{organization}/servers/{server}/sites/{site} geeft één 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 is een van laravel, symfony, statamic, wordpress, phpmyadmin, php, nextjs, nuxt, html, other en loadbalancer. status is installed als de site klaar is; terwijl hij verandert is het installing, updating of removing, en failed als dat misging. quick_deploy is deployen bij elke push; isolated zegt of de site als eigen Linux-gebruiker draait. Het environment-bestand en de deploy-URL van de site worden nooit teruggegeven.

Een site zoeken

GET /orgs/{organization}/sites geeft de sites op elke server waar je toegang toe hebt, gesorteerd op domein, elk met zijn server (ID en naam). De andere velden zijn dezelfde als hierboven. Maak de lijst kleiner met queryparameters:

Parameter Zoekt op
domain Het domein van de site, niet hoofdlettergevoelig.
id Het ID van de site.
server Het ID of de naam van de 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"
    }
  ]
}

Een token met alleen de scope Deploy mag dit ook aanroepen, om de site te vinden die hij deployt, maar moet dan domain of id meegeven; zonder is het antwoord 422. Past er niets, dan is data een lege lijst.

Deployments opvragen

GET /orgs/{organization}/servers/{server}/sites/{site}/deployments geeft de deployments van de site, de nieuwste eerst, 25 per pagina (zie paginering). GET …/deployments/{deployment} geeft er één.

{
  "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"
  }
}
Veld Waarden
status queued, running, succeeded, failed, cancelled
trigger manual, push, url (de deploy-URL), rollback, api
commit null tot de code is opgehaald.
release De releasemap, of live voor een site zonder zero-downtime deploys; null tot de deploy is gestart.

Een deployment starten

POST /orgs/{organization}/servers/{server}/sites/{site}/deployments deployt de branch van de site, precies zoals Deployen in de app. Er hoort geen body bij. Het antwoord is 202 Accepted met de nieuwe deployment; volg die met zijn 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"
  }
}
  • 409 als er al een deploy van de site draait; task_id in het antwoord is de lopende taak.
  • 422 als de site nog niet klaar is om te deployen of geen repository heeft.

Zie deployments voor wat een deploy doet.

Databases opvragen en aanmaken

GET /orgs/{organization}/servers/{server}/databases geeft de databases van de server, gesorteerd op naam.

{
  "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 maakt een database aan op de server. De body heeft één veld:

Veld Regels
name Verplicht. 1 tot 63 letters, cijfers en underscores, uniek op de 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 }
}

Het antwoord is 202: de database wordt door een taak op de server gemaakt. Zijn status is installing, daarna installed, of failed als de taak mislukt. De server moet actief zijn en een database geïnstalleerd hebben, anders is het antwoord 422.

Een database verwijderen

DELETE /orgs/{organization}/servers/{server}/databases/{database} verwijdert de database op de server. Het antwoord is 202 met de database, nu removing, en de taak die hem verwijdert in task_id, binnen data zoals bij elk endpoint dat een taak start:

{
  "data": { "id": 4, "server_id": 12, "name": "shop_staging", "status": "removing", "created_at": "2026-10-07T15:10:00+00:00", "task_id": 9123 }
}

Zie databases.

Back-ups opvragen en er een uitvoeren

GET /orgs/{organization}/servers/{server}/backups geeft de back-upconfiguraties van de server, gesorteerd op naam, elk met de 20 laatste back-ups. size is in bytes.

{
  "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 is minute, hourly, nightly, weekly, monthly, reboot of custom; schedule is de cron-expressie. De status van een back-up is running, succeeded of failed.

POST /orgs/{organization}/servers/{server}/backups/{backup}/run, met het ID van een back-upconfiguratie, start nu een back-up. Er hoort geen body bij en het antwoord is 202:

{ "data": { "backup_id": 141, "task_id": 9124 } }

409 als er al een back-up van die configuratie draait. Zie back-ups.

Recepten opvragen en er een uitvoeren

GET /orgs/{organization}/recipes geeft de recepten van de organisatie, gesorteerd op naam. run_as is root of 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 voert een recept uit op een of meer servers.

Veld Regels
servers Verplicht. Een lijst server-ID's, minstens één.
notify Optioneel, true of false (standaard). Met true krijg je een verslag per e-mail als elke server klaar is.
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 }
    ]
  }
}

Elke server die je noemt moet bestaan, binnen je toegang vallen en actief zijn. Anders draait het recept nergens en is het antwoord 422: errors.servers noemt de server-ID's die niet bestaan of waar je geen toegang toe hebt, of de namen van de servers die niet actief zijn. Het antwoord toont elke server met een eigen taak. Zie recepten.

Een taak volgen

Langer werk (een deploy, een database, een back-up, een recept op een server) draait als achtergrondtaak, dezelfde die je ziet onder activiteit. GET /orgs/{organization}/tasks/{task} geeft de stand en de 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 is queued, running, succeeded, failed of cancelled; de laatste drie zijn definitief. progress loopt van 0 tot 100. Als een taak mislukt, zegt error waarom. Vraag de taak om de paar seconden op tot de status definitief is.

Paginering

Alleen de lijst met deployments is gepagineerd, met 25 deployments per pagina, de nieuwste eerst. Vraag een andere pagina op met ?page=2. Het antwoord heeft links en meta naast 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 bevat ook een lijst links voor paginaknoppen. Volg links.next tot die null is. Alle andere lijsten geven alles in één antwoord.

Fouten

Fouten zijn JSON met een message:

{ "message": "shop.example.com is not ready to deploy yet." }
Status Betekenis
401 Geen token, een fout of ingetrokken token, of een verlopen token: {"message": "Unauthenticated."}
403 Het token mist de scope ("Invalid ability provided."), of je rol staat de wijziging niet toe ("Your role does not allow this.").
404 De organisatie, server, site of het andere item bestaat niet, of je hebt er geen toegang toe. Vertrouw niet op de message.
409 Hetzelfde werk draait al. Het antwoord bevat de task_id van de lopende taak.
422 Het verzoek kan niet worden uitgevoerd: ongeldige velden, of een reden zoals een server die nog niet klaar is.
429 Te veel verzoeken; zie rate limits.

Een 409 ziet er zo uit:

{ "message": "Deploying to shop.example.com is already running.", "task_id": 9121 }

Een 422 voor ongeldige velden noemt ze onder errors:

{
  "message": "The name field format is invalid.",
  "errors": {
    "name": ["The name field format is invalid."]
  }
}

Rate limits

Elk token mag 120 verzoeken per minuut doen. Elk antwoord heeft de headers X-RateLimit-Limit en X-RateLimit-Remaining. Boven de limiet antwoordt de API 429 met een header Retry-After: het aantal seconden dat je moet wachten.

Als je een taak opvraagt, is eens per paar seconden ruim genoeg.

Deployen vanuit GitHub Actions

Deze workflow deployt nadat de tests zijn geslaagd en faalt als de deploy mislukt. Maak een token met alleen de scope Deploy en voeg het toe aan de secrets van de repository als VIMONTO_TOKEN (Settings → Secrets and variables → Actions bij GitHub). Vul je eigen adres, organisatieslug, server-ID en site-ID in.

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    # needs: tests   # deploy pas nadat je testjob is geslaagd
    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")

          # Start de deploy; curl faalt bij 4xx/5xx, zoals 409 als er al een draait.
          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"

          # Volg de taak tot hij klaar is.
          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

Zet Deployen bij elke push uit voor de site als CI hem deployt. Anders start een push zelf al een deploy, en krijgt het verzoek van de pipeline 409 omdat er al een deploy draait.

Of gebruik de CLI

De Vimonto Deploy CLI vat deze verzoeken samen in één commando: deploy deploy shop.example.com --watch start de deploy, volgt de taak en stopt met het resultaat ervan. In CI leest hij het token uit DEPLOY_TOKEN.

Of gebruik de deploy-URL

Als je alleen een deploy wilt starten, is de geheime Deploy-URL van de site eenvoudiger: één POST zonder token, en niets om te volgen. Hij vertelt je pipeline niet of de deploy gelukt is. Zie deployments.

Veelgestelde vragen

Is een token gekoppeld aan één organisatie?

Nee. Een token bereikt elke organisatie waar je lid van bent, met je rol in elk. GET /user toont ze. Maak een apart account als een pipeline maar één organisatie mag bereiken.

Wat gebeurt er met mijn tokens als mijn rol verandert?

Een token volgt altijd je huidige rol en servertoegang. Verlies je een recht of verlaat je een organisatie, dan verliest het token dat ook, meteen.

Kan ik servers of sites aanmaken via de API?

Nog niet. De API dekt het opvragen van servers, sites, deployments, databases, back-ups, recepten en taken; deployen; databases aanmaken en verwijderen; en back-ups en recepten uitvoeren.

Waar vind ik het server- en site-ID?

In de adresbalk van de app: op de pagina's van een site is het adres /{organization}/servers/{server}/sites/{site}/…. GET /orgs/{organization}/servers en GET …/servers/{server}/sites tonen ze ook, en GET /orgs/{organization}/sites?domain=shop.example.com vindt een site met zijn server-ID op domein.