ControlX API

Orchestrator API Dokumentation

Vollständige REST-API für die Verwaltung von virtuellen Maschinen, Containern und Infrastruktur. Alle Panel-Funktionen laufen über diese API.

Basics

  • Base URL: https://api.bit-controlx.de/api/v1
  • Format: JSON (Content-Type: application/json)
  • Encoding: UTF-8
  • HTTP Methods: GET, POST, PATCH, PUT, DELETE

Authentifizierung

Bearer Token (Benutzer-Auth)

Für Panel-Benutzer via Laravel Sanctum:

Authorization: Bearer <token>

Token erhältst du via /auth/login

API-Key (Integrationen)

Alternativ wird ein API-Key im Header akzeptiert:

X-API-Key: <api_key>

Response Format

Erfolgreiche Response

{
  "data": { ...actual response data... },
  "meta": {
    "current_page": 1,
    "last_page": 5,
    "per_page": 50,
    "total": 237
  },
  "schema_version": "1.0",
  "errors": null
}

Fehler-Response

{
  "data": null,
  "meta": null,
  "schema_version": "1.0",
  "errors": {
    "message": "Validation failed",
    "details": {
      "email": ["The email field is required."]
    },
    "code": "VALIDATION_FAILED"
  }
}

HTTP Status Codes & Fehlercodes

Erfolgs-Codes (2xx)

  • 200 OK
    Anfrage erfolgreich verarbeitet. Bei GET: Daten zurückgegeben. Bei PUT/PATCH: Ressource aktualisiert.
  • 201 Created
    Neue Ressource wurde erstellt (POST-Anfragen). Response enthält die erstellte Ressource.
  • 202 Accepted
    Asynchrone Operation gestartet (z.B. Server-Erstellung, Backup). Die Aktion läuft im Hintergrund.
  • 204 No Content
    Ressource erfolgreich gelöscht. Kein Response-Body.

Client-Fehler (4xx)

  • 400 Bad Request
    Ungültige Anfrage-Syntax oder Parameter.
    Ursachen: Ungültiges JSON, fehlerhafter Content-Type Header, ungültige Query-Parameter.
  • 401 Unauthorized
    Authentifizierung fehlt oder ist ungültig.
    Ursachen: Kein Bearer Token, abgelaufener Token, ungültiger API-Key, Token widerrufen.
  • 403 Forbidden
    Authentifiziert, aber keine Berechtigung für diese Aktion.
    Ursachen: Keine Org-Admin-Rechte, falsches Projekt, API-Key ohne erforderlichen Scope, Server gehört anderem User.
  • 404 Not Found
    Ressource existiert nicht oder wurde gelöscht.
    Ursachen: Ungültige ID, bereits gelöschter Server/Projekt, Endpunkt falsch geschrieben.
  • 409 Conflict
    Konflikt mit aktuellem Zustand der Ressource.
    Ursachen: Slug bereits vergeben, E-Mail existiert bereits, Server läuft noch (beim Löschen).
  • 422 Unprocessable Entity
    Validierungsfehler - Daten sind syntaktisch korrekt aber semantisch ungültig.
    Ursachen: Pflichtfeld fehlt, ungültiges E-Mail-Format, Passwort zu kurz, ungültige flavor_id.
  • 429 Too Many Requests
    Rate-Limit überschritten.
    Lösung: Warten Sie die im Retry-After Header angegebene Zeit ab (Standard: 60 Requests/Minute).

Server-Fehler (5xx)

  • 500 Internal Server Error
    Unerwarteter Serverfehler.
    Ursachen: Datenbankfehler, Provider-Verbindungsproblem, interner Bug. Bitte Support kontaktieren.
  • 502 Bad Gateway
    Proxmox-Host nicht erreichbar.
    Ursachen: Host offline, Netzwerkproblem, Proxmox-API antwortet nicht.
  • 503 Service Unavailable
    Service temporär nicht verfügbar.
    Ursachen: Wartungsarbeiten, Überlastung. Versuchen Sie es später erneut.

Fehler-Response Format

Bei Fehlern enthält die Response immer folgende Struktur:

{
  "message": "The given data was invalid.",
  "errors": {
    "email": [
      "The email field is required.",
      "The email must be a valid email address."
    ],
    "password": [
      "The password must be at least 8 characters."
    ]
  }
}

Typische Fehlermeldungen

Meldung Bedeutung
Unauthenticated. Token fehlt oder ist abgelaufen → neu einloggen
Forbidden. Keine Berechtigung für diese Ressource
Server not found. Server-ID existiert nicht oder wurde gelöscht
Organization not found. Organisation mit dieser ID existiert nicht
organization_id is required. Query-Parameter organization_id muss angegeben werden
project_id or organization_id is required. Mindestens einer der beiden Parameter erforderlich
Invalid action. Unbekannte Server-Aktion (erlaubt: start, stop, reboot, shutdown)
Server is not running. Stop/Reboot auf gestopptem Server nicht möglich
The slug has already been taken. Slug muss eindeutig sein → anderen wählen
Limit reached. Maximale Anzahl Server/User erreicht → Limit erhöhen

Authentifizierung

POST /auth/login

Authentifiziert einen Benutzer und gibt ein Access Token zurück.

Request Body

  • email required email
  • password required string

Beispiel Request

curl --location -X POST https://api.bit-controlx.de/api/v1/auth/login \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "owner@example.test",
    "password": "Geheim123"
  }'
Response (200 OK):
{
  "data": {
    "user": {
      "id": 7,
      "name": "Max Mustermann",
      "email": "max@example.com",
      "is_super_admin": false,
      "email_verified_at": null,
      "two_factor_confirmed_at": null,
      "two_factor_allowed": true,
      "created_at": "2026-02-07T03:04:38.000000Z",
      "updated_at": "2026-02-07T03:20:13.000000Z"
    },
    "token": "105|vmWHbSI3Paum8lIJxbeDaRmPc7WBSdBC8Q6v0TiM277d2519"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Berechtigung: Für API-Keys ist der Scope read:servers erforderlich.

GET /auth/me

Gibt Informationen über den aktuell authentifizierten Benutzer zurück.

Beispiel Request

curl --location -X GET https://api.bit-controlx.de/api/v1/auth/me \
  -H "Accept: application/json" \
  -H "Authorization: Bearer 54|aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2uV3wX4yZ5"
Response (200 OK):
{
  "data": {
    "id": 7,
    "name": "Max Mustermann",
    "email": "max@example.com",
    "is_super_admin": false,
    "email_verified_at": null,
    "two_factor_confirmed_at": null,
    "two_factor_allowed": true,
    "created_at": "2026-02-07T03:04:38.000000Z",
    "updated_at": "2026-02-07T03:20:13.000000Z"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

PUT /auth/me

Aktualisiert die Daten des aktuell authentifizierten Benutzers.

  • name optional string (max: 255)
  • email optional email (unique)
  • password optional string (min: 8)
Response (200 OK):
{
  "data": {
    "id": 7,
    "name": "Max Updated",
    "email": "max@example.com",
    "is_super_admin": false,
    "email_verified_at": null,
    "two_factor_confirmed_at": null,
    "two_factor_allowed": true,
    "created_at": "2026-02-07T03:04:38.000000Z",
    "updated_at": "2026-02-07T03:20:13.000000Z"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

POST /auth/logout

Widerruft das aktuelle Access Token.

curl --location -X POST https://api.bit-controlx.de/api/v1/auth/logout \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"

Response: 204 No Content

Two-Factor Authentifizierung

GET /two-factor/status

Gibt den aktuellen 2FA-Status des Benutzers zurück.

Response (200 OK):
{
  "data": {
    "allowed": true,
    "enabled": false,
    "confirmed": false,
    "recovery_codes_count": 0
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

Organisationen

GET /organizations

Liste aller Organisationen des Benutzers.

Response (200 OK):
{
  "data": [
    {
      "id": 5,
      "name": "Meine Organisation",
      "slug": "meine-organisation",
      "external_id": null,
      "host_id": 1,
      "active": true,
      "created_at": "2026-02-07T03:52:32.000000Z",
      "updated_at": "2026-02-07T03:52:34.000000Z",
      "server_scope": "user"
    }
  ],
  "meta": {
    "current_page": 1,
    "first_page_url": "https://api.bit-controlx.de/api/v1/organizations?page=1",
    "from": 1,
    "last_page": 1,
    "last_page_url": "https://api.bit-controlx.de/api/v1/organizations?page=1",
    "links": [...],
    "next_page_url": null,
    "path": "https://api.bit-controlx.de/api/v1/organizations",
    "per_page": 50,
    "prev_page_url": null,
    "to": 1,
    "total": 1
  },
  "schema_version": "1.0",
  "errors": null
}

POST /organizations

Erstellt eine neue Organisation.

Request Body

  • name required string (max: 255)
    Name der Organisation
  • slug optional string (max: 255, unique)
    URL-freundlicher Identifier (wird automatisch aus Name generiert falls nicht angegeben)
  • external_id optional string (max: 255, unique)
    Externe ID für Integrationen
  • host_id optional integer
    Zugewiesener Host
  • active optional boolean
    Aktivstatus (Standard: true)
curl --location -X POST https://api.bit-controlx.de/api/v1/organizations \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Meine Organisation"
  }'
Response (201 Created):
{
  "data": {
    "name": "Meine Organisation",
    "slug": "meine-organisation",
    "host_id": 1,
    "updated_at": "2026-02-07T03:52:32.000000Z",
    "created_at": "2026-02-07T03:52:32.000000Z",
    "id": 5
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /organizations/{id}

Details einer Organisation.

Response (200 OK):
{
  "data": {
    "id": 5,
    "name": "Meine Organisation",
    "slug": "meine-organisation",
    "external_id": null,
    "host_id": 1,
    "active": true,
    "created_at": "2026-02-07T03:52:32.000000Z",
    "updated_at": "2026-02-07T03:52:32.000000Z",
    "server_scope": "user"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

PATCH /organizations/{id}

Aktualisiert eine Organisation.

Response (200 OK):
{
  "data": {
    "id": 5,
    "name": "Organisation Updated",
    "slug": "meine-organisation",
    "external_id": null,
    "host_id": 1,
    "active": true,
    "created_at": "2026-02-07T03:52:32.000000Z",
    "updated_at": "2026-02-07T03:52:34.000000Z",
    "server_scope": "user"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

DELETE /organizations/{id}

Löscht eine Organisation.

Response: 204 No Content

Organisations-Benutzer

GET /organizations/{id}/users

Liste aller Benutzer einer Organisation.

Response (200 OK):
{
  "data": [
    {
      "id": 7,
      "name": "Max Mustermann",
      "email": "max@example.com",
      "pivot": {
        "organization_id": 5,
        "user_id": 7,
        "role": "owner",
        "created_at": "2026-02-07T03:52:32.000000Z",
        "updated_at": "2026-02-07T03:52:32.000000Z"
      }
    }
  ],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Rollen: owner = Vollzugriff, admin = Verwaltung, member = Standardbenutzer

Benutzer

GET /users

Listet Benutzer der Organisation auf (nur Owner/Admin).

Query Parameter

  • organization_id optional integer
    Erforderlich, wenn der Account mehreren Organisationen zugeordnet ist.

Beispiel Request

curl --location -X GET "https://api.bit-controlx.de/api/v1/users?organization_id=5" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"

POST /users

Erstellt einen neuen Benutzer und ordnet ihn der Organisation zu (nur Owner/Admin).

Request Body

  • name required string (max: 255)
  • email required email (unique)
  • password required string (min: 8)
  • organization_id optional integer
    Optional im Body, alternativ per Query-Parameter.
  • role optional enum (admin, user)
    admin kann nur durch Owner vergeben werden.

Beispiel Request

curl --location -X POST "https://api.bit-controlx.de/api/v1/users?organization_id=5" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Anna Admin",
    "email": "anna@example.com",
    "password": "SicheresPasswort123",
    "role": "user"
  }'
Response (201 Created):
{
  "data": {
    "id": 42,
    "name": "Anna Admin",
    "email": "anna@example.com",
    "updated_at": "2026-02-07T09:00:00.000000Z",
    "created_at": "2026-02-07T09:00:00.000000Z"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

Projekte

GET /projects

Liste aller Projekte des Benutzers.

Response (200 OK):
{
  "data": [
    {
      "id": 11,
      "organization_id": 5,
      "name": "Mein Projekt",
      "slug": "mein-projekt",
      "external_id": null,
      "active": true,
      "created_at": "2026-02-07T03:52:36.000000Z",
      "updated_at": "2026-02-07T03:52:36.000000Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 50,
    "total": 1
  },
  "schema_version": "1.0",
  "errors": null
}

POST /projects

Erstellt ein neues Projekt.

Request Body

  • name required string (max: 255)
  • organization_id required integer
Response (201 Created):
{
  "data": {
    "organization_id": 5,
    "name": "Mein Projekt",
    "slug": "mein-projekt",
    "updated_at": "2026-02-07T03:52:36.000000Z",
    "created_at": "2026-02-07T03:52:36.000000Z",
    "id": 11
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /projects/{id}

Details eines Projekts (inkl. Organisation).

Response (200 OK):
{
  "data": {
    "id": 11,
    "organization_id": 5,
    "name": "Mein Projekt",
    "slug": "mein-projekt",
    "external_id": null,
    "active": true,
    "created_at": "2026-02-07T03:52:36.000000Z",
    "updated_at": "2026-02-07T03:52:36.000000Z",
    "organization": {
      "id": 5,
      "name": "Meine Organisation",
      "slug": "meine-organisation",
      "external_id": null,
      "host_id": 1,
      "active": true,
      "created_at": "2026-02-07T03:52:32.000000Z",
      "updated_at": "2026-02-07T03:52:34.000000Z",
      "server_scope": "user"
    }
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

PATCH /projects/{id}

Aktualisiert ein Projekt.

Response (200 OK):
{
  "data": {
    "id": 11,
    "organization_id": 5,
    "name": "Projekt Updated",
    "slug": "mein-projekt",
    "external_id": null,
    "active": true,
    "created_at": "2026-02-07T03:52:36.000000Z",
    "updated_at": "2026-02-07T03:52:38.000000Z",
    "organization": {
      "id": 5,
      "name": "Meine Organisation",
      "slug": "meine-organisation",
      "external_id": null,
      "host_id": 1,
      "active": true,
      "created_at": "2026-02-07T03:52:32.000000Z",
      "updated_at": "2026-02-07T03:52:34.000000Z",
      "server_scope": "user"
    }
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /projects/{id}/access

Liste der Benutzer mit direktem Projekt-Zugriff.

Response (200 OK):
{
  "data": [],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

DELETE /projects/{id}

Löscht ein Projekt.

Response: 204 No Content

Limits & Quotas

GET /limits/servers

Zeigt Server-Limits und aktuelle Nutzung.

Response (200 OK):
{
  "data": {
    "quotas": {
      "organization": null,
      "project": null,
      "user": null
    },
    "usage": {
      "organization": {
        "cpu_cores": 0,
        "memory_mb": 0,
        "storage_gb": 0,
        "instances": 0
      },
      "project": null,
      "user": {
        "cpu_cores": 2,
        "memory_mb": 2000,
        "storage_gb": 2,
        "instances": 2
      }
    }
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /limits/users

Zeigt Benutzer-Limits und Quota-Informationen.

Response (200 OK):
{
  "data": {
    "organization": {
      "id": 5,
      "name": "Meine Organisation",
      "slug": "meine-organisation",
      "external_id": null,
      "host_id": 1,
      "active": true,
      "created_at": "2026-02-07T03:52:32.000000Z",
      "updated_at": "2026-02-07T03:52:34.000000Z",
      "server_scope": "user",
      "quota": null
    },
    "quota": null
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

Flavors

GET /flavors

Verfügbare Server-Pakete (CPU/RAM/Storage) zur Auswahl bei Server-Erstellung und Resize.

Liste aller verfügbaren Flavors.

curl --location -X GET https://api.bit-controlx.de/api/v1/flavors \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"
Response (200 OK):
{
  "data": [
    {
      "id": 1,
      "name": "S",
      "slug": "s",
      "cpu_cores": 2,
      "memory_mb": 4096,
      "storage_gb": 40,
      "storage_type": "ssd",
      "price_per_minute": "0.0031",
      "description": "Small workload",
      "active": true,
      "created_at": "2026-02-07T10:00:00.000000Z",
      "updated_at": "2026-02-07T10:00:00.000000Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 50,
    "total": 1
  },
  "schema_version": "1.0",
  "errors": null
}
Berechtigung: Für API-Keys ist der Scope read:servers erforderlich.

Install-Medien

Stellt nutzbare Referenzen für ISOs und Container-Templates bereit. Interne Storage-Pfade werden nicht benötigt.

GET /media/isos

Liste verfügbarer ISO-Referenzen für VM-Installationen.

GET /media/templates

Liste verfügbarer Template-Referenzen für Container.

Response (200 OK):
{
  "data": [
    {
      "reference": "Debian 13",
      "label": "Debian 13",
      "alias": "Debian 13",
      "name": "debian-13-standard_13.0-1_amd64.tar.zst",
      "size": 183500800
    },
    {
      "reference": "ubuntu-22.04-standard_22.04-1_amd64.tar.zst",
      "label": "ubuntu-22.04-standard_22.04-1_amd64.tar.zst",
      "alias": null,
      "name": "ubuntu-22.04-standard_22.04-1_amd64.tar.zst",
      "size": 176947200
    }
  ],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Hinweis: Für template_id und media_id kann die reference verwendet werden (Alias oder Dateiname).

Server

GET /servers

Liste aller Server, auf die der Benutzer Zugriff hat.

Query Parameter

  • page optional integer
    Seitenzahl (50 pro Seite)
curl --location -X GET "https://api.bit-controlx.de/api/v1/servers" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"
Response (200 OK):
{
  "data": [
    {
      "id": 28,
      "flavor_id": 4,
      "server_id": "116",
      "name": "web-server-prod",
      "type": "container",
      "cpu_cores": 2,
      "memory_mb": 4096,
      "storage_gb": 50,
      "status": "running",
      "last_synced_at": "2026-02-06T14:30:00.000000Z",
      "created_at": "2026-01-20T09:15:00.000000Z",
      "updated_at": "2026-02-06T14:30:00.000000Z"
    },
    {
      "id": 31,
      "flavor_id": 2,
      "server_id": "119",
      "name": "database-backup",
      "type": "vm",
      "cpu_cores": 4,
      "memory_mb": 8192,
      "storage_gb": 200,
      "status": "stopped",
      "last_synced_at": "2026-02-06T14:30:00.000000Z",
      "created_at": "2026-01-25T11:20:00.000000Z",
      "updated_at": "2026-02-06T14:30:00.000000Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "first_page_url": "https://api.bit-controlx.de/api/v1/servers?page=1",
    "from": 1,
    "last_page": 1,
    "last_page_url": "https://api.bit-controlx.de/api/v1/servers?page=1",
    "links": [
      {
        "url": null,
        "label": "« Previous",
        "page": null,
        "active": false
      },
      {
        "url": "https://api.bit-controlx.de/api/v1/servers?page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next »",
        "page": null,
        "active": false
      }
    ],
    "next_page_url": null,
    "path": "https://api.bit-controlx.de/api/v1/servers",
    "per_page": 50,
    "prev_page_url": null,
    "to": 2,
    "total": 2
  },
  "schema_version": "1.0",
  "errors": null
}

GET /servers/{id}

Details eines einzelnen Servers (inkl. Status-Sync).

curl --location -X GET "https://api.bit-controlx.de/api/v1/servers/33" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"
Response (200 OK):
{
  "data": {
    "id": 33,
    "provider": "proxmox",
    "organization_id": 5,
    "project_id": 11,
    "user_id": 7,
    "flavor_id": 4,
    "server_id": "113",
    "external_id": "113",
    "region": null,
    "az": null,
    "node": "01KGRJM6HANRY5EFZETEYKNCJ8",
    "name": "web-server-prod",
    "type": "container",
    "cpu_cores": 1,
    "memory_mb": 1000,
    "storage_gb": 1,
    "status": "stopped",
    "last_synced_at": "2026-02-07T03:52:49.000000Z",
    "created_at": "2026-02-07T03:52:43.000000Z",
    "updated_at": "2026-02-07T03:52:49.000000Z"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /servers/{id}/status

Aktueller Server-Status direkt vom Provider.

Response Beispiel:
{
  "data": {
    "ha": {
      "managed": 0
    },
    "lock": "create",
    "cpu": 0,
    "disk": 0,
    "maxdisk": 4294967296,
    "status": "stopped",
    "swap": 0,
    "uptime": 0,
    "diskread": 0,
    "type": "lxc",
    "maxmem": 536870912,
    "vmid": 113,
    "cpus": 24,
    "netin": 0,
    "name": "CT113",
    "mem": 0,
    "diskwrite": 0,
    "netout": 0,
    "maxswap": 0
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /servers/{id}/config

Provider-Konfiguration des Servers.

Response Beispiel:
{
  "data": {
    "lock": "create",
    "digest": "a7e9f8c42935261b36fcd1d7d6cd8cd41648da49"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Hinweis: Die Konfiguration variiert je nach Server-Typ (LXC vs. VM) und kann bei laufenden Servern mehr Felder enthalten (cores, memory, rootfs, etc.).

GET /servers/{id}/metrics

Server-Metriken (CPU, RAM, Disk, Network) über einen Zeitraum.

Query Parameter

  • timeframe optional string
    Zeitraum: hour, day, week, month, year (Standard: hour)
Response Beispiel (gekürzt):
{
  "data": [
    {
      "time": 1770354840
    },
    {
      "time": 1770354900
    },
    {
      "maxmem": 4294967296,
      "maxcpu": 2,
      "maxdisk": 53687091200,
      "disk": 15728640000,
      "mem": 2147483648,
      "cpu": 0.15,
      "netin": 125829120,
      "netout": 98304000,
      "time": 1770357840
    },
    {
      "maxmem": 4294967296,
      "maxcpu": 2,
      "maxdisk": 53687091200,
      "disk": 15728640000,
      "mem": 2199023255,
      "cpu": 0.18,
      "netin": 125935488,
      "netout": 98410496,
      "time": 1770357900
    }
  ],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Hinweis: Datenpunkte ohne CPU/RAM-Werte sind Zeitpunkte, an denen der Server gestoppt war. Werte sind in Bytes (memory, disk) bzw. als Dezimalwerte (cpu: 0-1 pro Core).

GET /servers/{id}/network

Netzwerk-Interfaces des Servers.

Response (200 OK):
{
  "data": null,
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
VM-Hinweis: Für VMs benötigt dieser Endpunkt den QEMU Guest Agent. Ohne Guest Agent wird null zurückgegeben.

GET /servers/{id}/events

Event-Historie des Servers (paginiert, 50 pro Seite).

Response (200 OK):
{
  "data": [
    {
      "id": 144,
      "server_id": 33,
      "user_id": 7,
      "action": "status",
      "status": "stopped",
      "meta": null,
      "created_at": "2026-02-07T03:52:49.000000Z",
      "updated_at": "2026-02-07T03:52:49.000000Z"
    },
    {
      "id": 143,
      "server_id": 33,
      "user_id": 7,
      "action": "create",
      "status": null,
      "meta": {
        "flavor_id": 4,
        "type": "container"
      },
      "created_at": "2026-02-07T03:52:43.000000Z",
      "updated_at": "2026-02-07T03:52:43.000000Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "first_page_url": "https://api.bit-controlx.de/api/v1/servers/33/events?page=1",
    "from": 1,
    "last_page": 1,
    "last_page_url": "https://api.bit-controlx.de/api/v1/servers/33/events?page=1",
    "next_page_url": null,
    "path": "https://api.bit-controlx.de/api/v1/servers/33/events",
    "per_page": 50,
    "prev_page_url": null,
    "to": 2,
    "total": 2
  },
  "schema_version": "1.0",
  "errors": null
}

POST /servers

Erstellt einen neuen Server (VM oder Container).

Voraussetzungen: Nur Owner/Admin in der Organisation dürfen Server erstellen. Für API-Keys ist write:servers erforderlich. flavor_id ist für Kunden verpflichtend (Trusted Panel/Super-Admin ausgenommen).

Request Body

  • type required enum (vm, container)
    Server-Typ (auch "virtualization" oder "kind" akzeptiert)
  • name optional string (max: 255)
    Server-Name (wird DNS-safe normalisiert)
  • flavor_id required integer
    Flavor für CPU/RAM/Disk Specs
  • template_id required für Container string
    Template-Referenz (empfohlen: Dateiname, z. B. ubuntu-22.04-standard_22.04-1_amd64.tar.zst)
  • media_id optional für VM string
    ISO-Referenz (empfohlen: Dateiname, z. B. ubuntu-22.04-server-amd64.iso)
  • organization_id optional integer
    Ziel-Organisation. Wenn nicht gesetzt, nutzt die API bei eindeutiger Zuordnung die einzige verfügbare Organisation.
  • project_id optional integer
    Optionales Projekt. Muss zur angegebenen Organisation gehören.
  • user_id optional integer
    Bei Organisationen mit server_scope=user erforderlich; User muss Mitglied der Organisation sein.

Beispiel: VM mit ISO

curl --location -X POST https://api.bit-controlx.de/api/v1/servers \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "vm",
    "name": "web-server-01",
    "flavor_id": 3,
    "media_id": "ubuntu-22.04-server-amd64.iso"
  }'

Beispiel: LXC Container

curl --location -X POST https://api.bit-controlx.de/api/v1/servers \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "container",
    "name": "app-container-01",
    "flavor_id": 2,
    "template_id": "ubuntu-22.04-standard_22.04-1_amd64.tar.zst"
  }'
Response (202 Accepted):
{
  "data": {
    "status": "queued",
    "temp_password": "VXg8ykq7AVKtkfgx",
    "server": {
      "organization_id": 5,
      "project_id": 11,
      "user_id": 7,
      "flavor_id": 4,
      "server_id": "113",
      "name": "app-container-01",
      "type": "container",
      "cpu_cores": 1,
      "memory_mb": 1000,
      "storage_gb": 1,
      "status": null,
      "last_synced_at": null,
      "updated_at": "2026-02-07T03:52:43.000000Z",
      "created_at": "2026-02-07T03:52:43.000000Z",
      "id": 33,
      "temp_password": "VXg8ykq7AVKtkfgx"
    },
    "provisioning": {
      "started": false,
      "note": "Server was created in stopped state. Attach/select install media before first start if required."
    }
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

Server-Verwaltung

PATCH /servers/{id}

Aktualisiert Server-Konfiguration.

Request Body (optional)

  • name optional string
  • flavor_id optional integer
    Upgrade auf größeren Flavor
curl --location -X PATCH https://api.bit-controlx.de/api/v1/servers/33 \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"name": "web-server-updated"}'
Response (202 Accepted):
{
  "data": {
    "result": {
      "status": "queued"
    },
    "server": {
      "id": 33,
      "provider": "proxmox",
      "organization_id": 5,
      "project_id": 11,
      "user_id": 7,
      "flavor_id": 4,
      "server_id": "113",
      "external_id": "113",
      "region": null,
      "az": null,
      "node": "01KGRJM6HANRY5EFZETEYKNCJ8",
      "name": "web-server-updated",
      "type": "container",
      "cpu_cores": 1,
      "memory_mb": 1000,
      "storage_gb": 1,
      "status": "stopped",
      "last_synced_at": "2026-02-07T03:52:49.000000Z",
      "created_at": "2026-02-07T03:52:43.000000Z",
      "updated_at": "2026-02-07T03:52:57.000000Z"
    }
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Wichtig: Disks können nicht verkleinert werden. Flavor-Upgrades müssen größer sein.

POST /servers/{id}/reinstall

Reinstalliert eine VM mit neuem ISO (nur VMs).

Request Body

  • media_id required string
    ISO-Image für Neuinstallation
curl --location -X POST https://api.bit-controlx.de/api/v1/servers/156/reinstall \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "media_id": "debian-12-amd64.iso"
  }'

POST /servers/{id}/bootdisk

Entfernt ISO aus Boot-Reihenfolge (nur VMs).

DELETE /servers/{id}

Löscht einen Server permanent.

curl --location -X DELETE https://api.bit-controlx.de/api/v1/servers/33 \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"
Response (202 Accepted):
{
  "data": {
    "result": {
      "status": "deleted"
    },
    "server": {
      "id": 33,
      "organization_id": 5,
      "project_id": 11,
      "user_id": 7,
      "flavor_id": 4,
      "server_id": "113#deleted-33",
      "external_id": "113",
      "region": null,
      "az": null,
      "node": "01KGRJM6HANRY5EFZETEYKNCJ8",
      "name": "web-server-prod",
      "type": "container",
      "cpu_cores": 1,
      "memory_mb": 1000,
      "storage_gb": 1,
      "status": "deleted",
      "last_synced_at": "2026-02-07T03:52:49.000000Z",
      "created_at": "2026-02-07T03:52:43.000000Z",
      "updated_at": "2026-02-07T03:53:24.000000Z"
    }
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

POST /servers/sync

Synchronisiert alle Server mit dem Provider (nur Panel-Service oder Super-Admin).

Response Beispiel:
{
  "data": {
    "synced": 42,
    "created": 2,
    "updated": 15,
    "deleted": 1
  },
  "schema_version": "1.0"
}

Server-Aktionen

POST /servers/{id}/action

Führt Power-Aktionen auf dem Server aus.

Request Body

  • action required enum
    start | stop | shutdown | reboot | reset
Hinweis: reset wird bei Containern nicht unterstützt.

Beispiel Request

curl --location -X POST https://api.bit-controlx.de/api/v1/servers/116/action \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"action": "start"}'
Response (202 Accepted):
{
  "data": {
    "status": "queued"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

Verfügbare Aktionen

  • start Startet einen gestoppten Server
  • stop Hartes Stoppen (sofort)
  • shutdown Sauberes Herunterfahren (ACPI)
  • reboot Neustart des Servers
  • reset Hardware-Reset (nur VMs)
Action-Unterschiede:
stop = Hartes Stoppen (sofort)
shutdown = Sauberes Herunterfahren (ACPI)
reset = Hardware-Reset (wie Reset-Knopf)

Console & Terminal

Hinweis: WebSocket-Endpunkte sind aktuell nicht dokumentiert.

Server-Zugriffsverwaltung

GET /servers/{id}/access

Liste aller Benutzer mit direktem Server-Zugriff.

Response (200 OK):
{
  "data": [],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

POST /servers/{id}/access

Gewährt einem Benutzer direkten Zugriff auf den Server.

Request Body

  • user_id required integer
  • permission optional enum (view, control)
    Standard: view
curl --location -X POST https://api.bit-controlx.de/api/v1/servers/156/access \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": 42,
    "permission": "view"
  }'

PATCH /servers/{server_id}/access/{user_id}

Aktualisiert die Berechtigung eines Benutzers.

curl --location -X PATCH https://api.bit-controlx.de/api/v1/servers/156/access/42 \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "permission": "control"
  }'

DELETE /servers/{server_id}/access/{user_id}

Entzieht einem Benutzer den direkten Server-Zugriff.

Server-Gruppen

Server-Gruppen ermöglichen die logische Gruppierung von Servern für bessere Organisation.

GET /server-groups

Liste aller Server-Gruppen des Projekts/der Organisation.

Query Parameter

  • project_id conditionally required integer
    Filtert nach Projekt (entweder project_id oder organization_id erforderlich)
  • organization_id conditionally required integer
    Filtert nach Organisation (entweder project_id oder organization_id erforderlich)
  • include optional string
    Wert: servers - inkludiert Server in Response
Response (200 OK):
{
  "data": [],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

POST /server-groups

Erstellt eine neue Server-Gruppe.

Request Body

  • name required string (max: 255)
    Name der Gruppe
  • project_id conditionally required integer
    Entweder project_id oder organization_id muss gesetzt sein
  • organization_id conditionally required integer
    Entweder organization_id oder project_id muss gesetzt sein
  • sort_order optional integer (min: 0)
    Sortierreihenfolge der Gruppe
curl --location -X POST https://api.bit-controlx.de/api/v1/server-groups \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Servers",
    "project_id": 5
  }'
Response (201 Created):
{
  "data": {
    "organization_id": 5,
    "project_id": 11,
    "name": "Production Servers",
    "sort_order": 1,
    "created_by": 7,
    "updated_at": "2026-02-07T03:53:10.000000Z",
    "created_at": "2026-02-07T03:53:10.000000Z",
    "id": 10
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Response mit include=servers:
{
  "data": [
    {
      "id": 10,
      "organization_id": 5,
      "project_id": 11,
      "name": "Production Servers",
      "sort_order": 1,
      "created_by": 7,
      "created_at": "2026-02-07T03:53:10.000000Z",
      "updated_at": "2026-02-07T03:53:11.000000Z",
      "items": [
        {
          "server_id": 33,
          "position": 1,
          "server": {
            "id": 33,
            "server_id": "113",
            "name": "web-server-prod",
            "status": "running",
            "type": "container",
            "cpu_cores": 1,
            "memory_mb": 1000,
            "storage_gb": 1
          }
        }
      ]
    }
  ],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

POST /server-groups/{id}/servers

Fügt Server zur Gruppe hinzu.

Request Body

  • server_ids required array of integers (min: 1 Element)
    IDs der Server die hinzugefügt werden sollen
Response (200 OK):
{
  "data": true,
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

DELETE /server-groups/{id}/servers/{serverId}

Entfernt einen Server aus der Gruppe.

Response: 204 No Content

PATCH /server-groups/{id}

Aktualisiert eine Server-Gruppe (Name ändern).

Response (200 OK):
{
  "data": {
    "id": 10,
    "organization_id": 5,
    "project_id": 11,
    "name": "Gruppe Updated",
    "sort_order": 1,
    "created_by": 7,
    "created_at": "2026-02-07T03:53:10.000000Z",
    "updated_at": "2026-02-07T03:53:11.000000Z"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

DELETE /server-groups/{id}

Löscht eine Server-Gruppe (Server bleiben erhalten).

Response: 204 No Content

Backups

Verwalten Sie geplante Backup-Jobs für Ihre Server. Backups werden vom Provider (z.B. Proxmox) ausgeführt.

GET /servers/{server}/backups/jobs

Liste aller Backup-Jobs für einen Server.

curl --location -X GET https://api.bit-controlx.de/api/v1/servers/116/backups/jobs \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"
Response (200 OK):
{
  "data": [],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

POST /servers/{server}/backups/jobs

Erstellt einen neuen geplanten Backup-Job.

Request Body

  • storage optional string
    Ziel-Storage für Backups
  • schedule optional string
    Cron-Schedule (z.B. "0 2 * * *" = täglich 2 Uhr)
  • mode optional string
    Backup-Modus: snapshot, suspend, stop (Standard: snapshot)
  • compress optional string
    Komprimierung: lzo, gzip, zstd
  • mailto optional string
    E-Mail für Benachrichtigungen
  • prune_backups optional string
    Retention Policy (z.B. "keep-last=5,keep-weekly=2")
curl --location -X POST https://api.bit-controlx.de/api/v1/servers/116/backups/jobs \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "storage": "backup-storage",
    "schedule": "0 3 * * *",
    "mode": "snapshot",
    "compress": "zstd",
    "prune_backups": "keep-last=7"
  }'

POST /servers/{server}/backups/run

Startet ein sofortiges Backup (unabhängig vom Schedule).

curl --location -X POST https://api.bit-controlx.de/api/v1/servers/116/backups/run \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "snapshot",
    "storage": "backup-storage"
  }'
Response (202 Accepted):
{
  "data": {
    "upid": "UPID:proxmoxhost:001223AA:05DFABD3:6986B724:vzdump:113:root@pam!ControlX-API:"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Hinweis: Backups werden asynchron ausgeführt. Die Response enthält eine Task-ID (UPID) zur Statusabfrage.

PATCH /servers/{server}/backups/jobs/{jobId}

Aktualisiert einen Backup-Job.

DELETE /servers/{server}/backups/jobs/{jobId}

Löscht einen Backup-Job.

Backup-Modi:
snapshot = Schnell, keine Downtime (empfohlen)
suspend = Kurze Pause während Backup
stop = Server wird gestoppt während Backup

API-Keys

Erstellen und verwalten Sie API-Keys für programmatischen Zugriff. API-Keys können mit spezifischen Scopes eingeschränkt werden.

GET /api-keys/scopes

Liste aller verfügbaren Scopes für API-Keys.

Response (200 OK):
{
  "data": {
    "scopes": [
      "read:servers",
      "write:servers",
      "read:organizations",
      "write:organizations",
      "read:projects",
      "write:projects",
      "read:users",
      "write:users",
      "read:billing",
      "admin"
    ]
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /api-keys

Liste aller API-Keys des aktuellen Benutzers.

Response (200 OK):
{
  "data": [],
  "meta": {
    "current_page": 1,
    "first_page_url": "https://api.bit-controlx.de/api/v1/api-keys?page=1",
    "from": null,
    "last_page": 1,
    "last_page_url": "https://api.bit-controlx.de/api/v1/api-keys?page=1",
    "next_page_url": null,
    "path": "https://api.bit-controlx.de/api/v1/api-keys",
    "per_page": 50,
    "prev_page_url": null,
    "to": null,
    "total": 0
  },
  "schema_version": "1.0",
  "errors": null
}

POST /api-keys

Erstellt einen neuen API-Key.

Request Body

  • name required string (max: 255)
    Name zur Identifikation
  • scopes required array of strings
    Liste der Berechtigungen (mindestens 1 Scope erforderlich)
  • project_id optional integer
    Beschränkt Key auf ein Projekt
  • expires_at optional datetime
    Ablaufdatum (ISO 8601, muss in der Zukunft liegen)
  • active optional boolean
    Aktivstatus (Standard: true)
curl --location -X POST https://api.bit-controlx.de/api/v1/api-keys \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI/CD Pipeline",
    "scopes": ["read:servers", "read:projects"]
  }'
Response (201 Created):
{
  "data": {
    "id": 15,
    "name": "CI/CD Pipeline",
    "active": null,
    "scopes": [
      "read:servers",
      "read:projects"
    ],
    "expires_at": null,
    "user_id": 7,
    "project_id": null,
    "plain_key": "CLbeRs0dxM29ErW5Zoqd0LpSAPjJBt1QykEyYSz3"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Wichtig: Der plain_key wird nur einmalig bei der Erstellung zurückgegeben. Speichern Sie ihn sicher - er kann nicht erneut abgerufen werden!
Hinweis: Der Scope admin ist für Trusted Panel oder Super-Admins reserviert.

POST /api-keys/{id}/rotate

Rotiert den API-Key (generiert neuen Token).

Response (200 OK):
{
  "data": {
    "id": 15,
    "name": "CI/CD Pipeline",
    "plain_key": "VHkfC0tFkkOCRqGgfqgOB9CKn1oN3pM6Png7dS38"
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

DELETE /api-keys/{id}

Löscht einen API-Key permanent.

Response: 204 No Content

Billing

GET /billing/servers/{id}

Billing-Details für einen einzelnen Server mit Kostenaufschlüsselung.

curl --location -X GET "https://api.bit-controlx.de/api/v1/billing/servers/116" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"
Response (200 OK):
{
  "data": {
    "server_id": "113",
    "from": "2026-02-07T03:52:43.000000Z",
    "to": "2026-02-07T03:53:21.848568Z",
    "minutes": 0,
    "cost": 0,
    "segments": [
      {
        "flavor_id": 4,
        "minutes": 0,
        "rate": 0,
        "cost": 0
      }
    ]
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}
Billing-Segmente: Wenn ein Server seinen Flavor ändert, werden mehrere Segmente mit unterschiedlichen Raten erstellt. Die Gesamtkosten sind die Summe aller Segmente.

GET /billing/summary

Billing-Zusammenfassung für alle Server einer Organisation.

Query Parameter

  • organization_id required integer
Response (200 OK):
{
  "data": {
    "minutes": 567,
    "cost": 2.835,
    "servers": [
      {
        "server_id": "113",
        "from": "2026-02-07T03:52:43.000000Z",
        "to": "2026-02-07T03:53:20.166502Z",
        "minutes": 0,
        "cost": 0,
        "segments": [
          {
            "flavor_id": 4,
            "minutes": 0,
            "rate": 0,
            "cost": 0
          }
        ]
      }
    ]
  },
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /billing/snapshots

Liste aller Billing-Snapshots (Abrechnungsperioden).

Query Parameter

  • organization_id required integer
  • include_items optional boolean
    Inkludiert einzelne Billing-Items
Response (200 OK):
{
  "data": [],
  "meta": null,
  "schema_version": "1.0",
  "errors": null
}

GET /billing/snapshots/{id}

Details eines einzelnen Billing-Snapshots.

POST /billing/snapshots

Erstellt einen neuen Billing-Snapshot für die aktuelle Abrechnungsperiode.

Query Parameter

  • organization_id required integer
curl --location -X POST https://api.bit-controlx.de/api/v1/billing/snapshots \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <TOKEN>"