VRAMfarm-Logo VRAMfarm
DE
Registrieren
Dokumentation

VRAMfarm API

Starten Sie GPU-Server aus Skripten und CI: freie Maschine finden, mit einer fertigen App oder Ihrem eigenen Docker-Image starten, auf SSH warten, stoppen. Einfaches HTTPS und JSON, kein SDK nötig.

Basis-URL der APIhttps://vramfarm.com/api
  • Antworten kommen als JSON in UTF-8. POST-Anfragen brauchen den Header Content-Type: application/json.
  • Beträge sind in Euro. price ist der Stundenpreis für den ganzen Server inklusive aller Karten, als Dezimalzahl mit Cent (zum Beispiel 0.39).
  • Zeitangaben in Antworten sind ISO 8601 in UTC; das Feld updated im Katalog ist in Unix-Millisekunden.
  • Fehlermeldungen kommen in der Sprache Ihres Kontos oder in der Sprache aus dem Header Accept-Language, ersatzweise auf Englisch.

Schnellstart

Das Skript startet einen Server mit RTX 4090, wartet, bis er bereit ist, gibt den SSH-Befehl aus und stoppt den Server wieder, auch wenn unterwegs etwas schiefgeht.

Starten, auf SSH warten, stoppen
import os, time, requests

API = "https://vramfarm.com/api"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {os.environ['GF_TOKEN']}"

r = s.post(f"{API}/instances", json={"gpu": "rtx-4090", "count": 1, "template": "pytorch"})
r.raise_for_status()
sid = r.json()["id"]
try:
    while True:
        srv = s.get(f"{API}/instances/{sid}").json()
        if srv["status"] == "running":
            break
        if srv["status"] == "stopped":
            raise RuntimeError(srv["error"])
        print(srv["stage_note"] or srv["stage"])
        time.sleep(10)
    print(srv["access"]["ssh"]["command"])
    # your work goes here: ssh, scp, requests to the app on the server
finally:
    s.post(f"{API}/instances/stop", json={"id": sid})

Authentifizierung

Erstellen Sie einen Token im Dashboard → Einstellungen → API-Tokens. Ein Token sieht aus wie gf_live_… und wird nur einmal angezeigt: Legen Sie ihn in den Secrets Ihrer CI oder in der Umgebungsvariable GF_TOKEN ab. Am selben Ort können Sie Tokens widerrufen. Bis zu 10 Tokens können gleichzeitig aktiv sein.

Senden Sie den Token im Header Authorization: Bearer gf_live_…. Mehr ist nicht nötig: Anfragen werden nicht signiert, es gibt keinen Zeitstempel und kein recvWindow, und bei Anfragen mit Token werden Cookies und Origin nicht geprüft.

import os, requests

H = {"Authorization": f"Bearer {os.environ['GF_TOKEN']}"}
print(requests.get("https://vramfarm.com/api/account", headers=H).json())

Ein Token gibt nur die Methoden auf dieser Seite frei. Passwort, SSH-Schlüssel und das Erstellen neuer Tokens gibt es nur im Dashboard; mit einem Token liefern diese Endpunkte 403. Wer an einen geleakten Token kommt, kann Server starten und stoppen, aber nicht Ihr Konto verwalten.

Der Katalog und /health funktionieren ohne Token. Senden Sie aber einen Authorization-Header mit falschem oder widerrufenem Token, liefert jeder Endpunkt 401.

Rufen Sie die API von Ihrem eigenen Server, Skript oder Ihrer CI auf. Anfragen aus dem Browser auf einer anderen Website gehen nicht durch, und dort könnte jeder Besucher den Token sehen.

Hinterlegen Sie vor dem ersten Start einen öffentlichen SSH-Schlüssel in den Dashboard-Einstellungen: Er wird auf jedem neuen Server installiert. Ob alles bereit ist, prüfen Sie mit GET /api/account.

Fehler und Limits

Bei einem Fehler erhalten Sie einen HTTP-Status und den Body {"error": "message", "code": "snake_case_code"}. Den Text in error können Sie Menschen unverändert anzeigen; verzweigen Sie im Code anhand von code, nie anhand des Texts. Manche Antworten enthalten zusätzlich einen Hinweis für Programme: unverified beim Start, saving beim Stoppen.

StatusWann
400Ungültige Parameter: Image, Festplatte, zu wenig VRAM, Server-Limit
401Falscher oder widerrufener Token, oder das Konto ist gesperrt
402Nicht genug Guthaben; error nennt den nötigen Betrag
403E-Mail-Adresse nicht bestätigt, oder die Methode ist mit einem Token nicht verfügbar
404Server nicht gefunden oder er gehört zu einem anderen Konto; unbekannter Endpunkt
409Keine Maschinen dieses Typs verfügbar; der Server-Ordner wird noch gespeichert
415POST ohne Content-Type: application/json
429Rate-Limit überschritten; warten Sie so viele Sekunden, wie der Header Retry-After angibt
500Ein Fehler auf unserer Seite
502Der Katalog ist vorübergehend nicht verfügbar
503Der Maschinenanbieter ist überlastet; starten Sie in einer Minute erneut

Limits

  • 60 Anfragen pro Minute und Token, über alle Methoden. Das Limit eines Tokens wirkt sich nicht auf andere aus.
  • 10 Starts pro Minute und Token. Fehlgeschlagene Starts zählen mit.
  • Der Katalog ist zusätzlich auf 60 Anfragen pro Minute und IP-Adresse begrenzt.
  • Bis zu 4 Server gleichzeitig; die genaue Zahl steht in max_active_instances. Sie brauchen mehr? Schreiben Sie uns.
  • Request-Body bis 64 KB.

Der Server-Status ändert sich höchstens alle paar Sekunden. Fragen Sie ihn daher alle 5–10 Sekunden ab.

Erneuter Versuch bei 429, 502 und 503
import time, requests

def call(method, url, **kw):
    for attempt in range(5):
        r = requests.request(method, url, **kw)
        if r.status_code not in (429, 502, 503):
            return r
        time.sleep(int(r.headers.get("Retry-After", 30)))
    return r

Katalog

Verfügbare Maschinen

GET/api/offers

Eine Liste verfügbarer Maschinen mit Preis in Euro pro Stunde, die günstigsten zuerst. Der Katalog wird alle 10 Minuten aktualisiert.

Query-Parameter

ParameterTypBeschreibung
gpuoptionalstringGPU-Modell, zum Beispiel h200. Ohne Angabe oder bei einem unbekannten Modell kommen alle Modelle zurück. Die Modellliste steht unter der Tabelle.
countoptionalintegerAnzahl der Karten in der Maschine: 1, 2, 4 oder 8. Andere Werte werden ignoriert.
alloptionalstring1 zeigt auch nicht verifizierte Maschinen. Standardmäßig nur verifizierte (verified: true).

Modelle: b200 h200 h100 a100 a100-40 l40s l40 l4 rtx-pro-6000 rtx-a6000 rtx-a5000 rtx-a4000 rtx-5090 rtx-5080 rtx-5070-ti rtx-4090 rtx-4080 rtx-4060-ti rtx-3090 rtx-3080 rtx-3060. a100 hat 80 GB, a100-40 hat 40 GB.

Felder einer Maschine
idintegerBeim Start als offer_id übergeben
gpu, gpu_namestringModell: Code für Anfragen und Anzeigename
num_gpusintegerAnzahl der Karten
vramintegerVRAM einer Karte, GB
cpu, cpu_cores, cpu_ghzstring, integer, numberCPU, verfügbare Kerne, Taktfrequenz
ramintegerRAM, GB
disk, disk_bwintegerWie viele GB Festplatte Sie belegen können; Festplattengeschwindigkeit, MB/s
net_down, net_upintegerNetzwerk, Mbit/s
countrystringLand, ISO-Code
reliabilitynumberZuverlässigkeit der Maschine von 0 bis 1
cuda, drivernumber, stringHöchste unterstützte CUDA- und Treiberversion
dlperf, tflops, mem_bw, pcienumberLeistung: DLPerf-Wert, TFLOPS, Speicher- und PCIe-Bandbreite
verifiedbooleanDie Maschine ist verifiziert
pricenumberEUR pro Stunde für den ganzen Server, inklusive der Mindestfestplatte des Templates
disk_eurnumberEUR pro Stunde für 1 GB Festplatte über der enthaltenen Menge
traffic_eur, traffic_up_eurnumberEUR pro 1 GB Traffic, Download wie Upload
durationintegerWie viele Tage die Maschine noch gemietet werden kann
static_ip, portsboolean, integerStatische IP, Anzahl offener Ports

Ist live gleich false, ist der Katalog abgeschaltet und offers leer. updated ist der Zeitpunkt der Antwort in Unix-Millisekunden.

Fehler

  • 401Falscher oder widerrufener Token
  • 429Mehr als 60 Anfragen pro Minute
  • 502Der Katalog ist vorübergehend nicht verfügbar; versuchen Sie es in einer Minute erneut
Anfrage
import os, requests

API = "https://vramfarm.com/api"
H = {"Authorization": f"Bearer {os.environ['GF_TOKEN']}"}

r = requests.get(f"{API}/offers", headers=H, params={"gpu": "h200", "count": 4})
r.raise_for_status()
for o in r.json()["offers"][:5]:
    print(o["id"], o["gpu_name"], o["price"], "EUR/h", o["country"])
Antwort · 200
{
  "live": true,
  "updated": 1761040000000,
  "offers": [
    {
      "id": 18273645,
      "gpu": "h200",
      "gpu_name": "H200",
      "num_gpus": 4,
      "vram": 141,
      "cpu": "AMD EPYC 9354",
      "cpu_cores": 64,
      "ram": 512,
      "disk": 2000,
      "net_down": 8000,
      "net_up": 8000,
      "country": "DE",
      "reliability": 0.998,
      "cuda": 12.8,
      "verified": true,
      "price": 33.16,
      "disk_eur": 0.00005,
      "traffic_eur": 0.007,
      "traffic_up_eur": 0.007
    }
  ]
}

Maschinentypen

GET/api/offer-types

Eine Zeile pro Paar „Modell × Anzahl Karten“: die günstigste Maschine mit einer Zuverlässigkeit ab 0,97 und wie viele solche Maschinen verfügbar sind. Praktisch, um gpu und count für einen Start zu wählen.

Keine Parameter.

Die Felder sind dieselben wie bei einer Maschine aus dem Katalog, dazu available, wie viele Maschinen dieses Typs frei sind, und max_dlperf, der beste Leistungswert darunter. Die Antwort wird eine Minute lang zwischengespeichert.

Fehler

  • 401Falscher oder widerrufener Token
  • 429Mehr als 60 Anfragen pro Minute
  • 502Der Katalog ist vorübergehend nicht verfügbar
Anfrage
import os, requests

API = "https://vramfarm.com/api"
H = {"Authorization": f"Bearer {os.environ['GF_TOKEN']}"}

types = requests.get(f"{API}/offer-types", headers=H).json()["types"]
for t in types:
    print(f'{t["num_gpus"]}x {t["gpu_name"]}: from {t["price"]} EUR/h, {t["available"]} available')
Antwort · 200
{
  "live": true,
  "updated": 1761040000000,
  "types": [
    {
      "id": 20311822,
      "gpu": "rtx-3090",
      "gpu_name": "RTX 3090",
      "num_gpus": 1,
      "vram": 24,
      "price": 0.3,
      "reliability": 0.991,
      "available": 37,
      "max_dlperf": 41
    }
  ]
}

Server

Server starten

POST/api/instances

Mietet eine Maschine und startet darauf die gewählte App oder Ihr Docker-Image. Die Antwort kommt sofort; bis der Server bereit ist, dauert es 2–5 Minuten, mit eigenem Image 8–15.

Request-Body, JSON

ParameterTypBeschreibung
offer_idoptionalintegerid der Maschine aus dem Katalog. Ist sie schon vergeben, wählen wir eine ähnliche desselben Typs. Entweder offer_id oder gpu ist Pflicht.
gpuoptionalstringModell, wenn die genaue Maschine egal ist: Wir nehmen die günstigste zuverlässige, die passt.
countoptionalintegerAnzahl der Karten bei Auswahl über gpu, 1 bis 8. Standard: 1.
templateoptionalstringWas laufen soll, standardmäßig pytorch. Siehe Tabelle unten. Ein unbekannter Wert wird als pytorch behandelt.
imageoptionalstringPflicht bei custom: ein öffentliches Image, geschrieben wie bei docker pull.
cmdoptionalstringBei custom: ein Befehl, der beim Start ausgeführt wird, bis zu 4000 Zeichen.
diskoptionalintegerFestplatte, GB. Weniger als das Minimum des Templates wird auf das Minimum angehoben. Höchstens 2000 und nicht mehr, als die Maschine hat.
ws_restoreoptionalbooleanStandard true: Ihr gespeicherter Arbeitsordner kommt zurück auf den Server. false liefert einen leeren Server.
Templates (template)
CodeWas drin istFestplatte abKartenspeicher ab
pytorchPyTorch, CUDA, Jupyter60 GB
jupyterJupyter40 GB
customIhr Image aus image60 GB
comfyuiComfyUI und Stable Diffusion 1.5100 GB
comfy-fluxComfyUI und Flux schnell100 GB16 GB
comfy-sdxlComfyUI und SDXL100 GB12 GB
comfy-wanComfyUI und Wan 2.2 5B, Video100 GB24 GB
comfy-wan14ComfyUI und Wan 2.2 14B, Video160 GB48 GB
comfy-qwenComfyUI und Qwen-Image100 GB24 GB
comfy-qeditComfyUI und Qwen-Image-Edit100 GB24 GB
comfy-hidreamComfyUI und HiDream-O160 GB24 GB
chatOpen WebUI und Ollama, Modell qwen3:8b80 GB12 GB
chat-proOpen WebUI und Ollama, Modell qwen3:32b100 GB24 GB
chat-mimoOpen WebUI und Ollama, Modell MiMo 9B60 GB12 GB
vllmvLLM, Modell Qwen/Qwen2.5-7B-Instruct100 GB
tts-qwen3Qwen3-TTS, Text zu Sprache, Gradio40 GB12 GB
tts-voxcpmVoxCPM2, Text zu Sprache, Gradio40 GB12 GB
tts-chatterboxChatterbox, Text zu Sprache, Gradio40 GB12 GB

Abgerechnet wird minutengenau ab dem Moment, in dem der Server running ist, mindestens 15 Minuten pro Start. Ihr Guthaben muss mindestens eine Stunde aller Ihrer Server einschließlich des neuen abdecken. Ist das Guthaben aufgebraucht, werden die Server gestoppt und ihre Festplatten gelöscht.

Eine identische Anfrage innerhalb von 15 Sekunden liefert den bereits erstellten Server mit "duplicate": true zurück; eine zweite Maschine mieten wir nicht. Scheitert ein Start am Guthaben oder an einer unbestätigten E-Mail-Adresse, wird er bei Anfragen mit Token nicht vorgemerkt: Starten Sie ihn selbst erneut.

Fehler

  • 400Keine GPU angegeben, ungültiges Image, Festplatte zu groß, zu wenig VRAM für das Template oder bereits 4 Server
  • 402Nicht genug Guthaben für eine Stunde; der Betrag steht in error
  • 403E-Mail-Adresse nicht bestätigt; die Antwort enthält "unverified": true
  • 409Keine Maschinen dieses Typs verfügbar
  • 429Mehr als 10 Starts pro Minute und Token
  • 503Der Maschinenanbieter ist überlastet; versuchen Sie es in einer Minute erneut
Anfrage
import os, requests

API = "https://vramfarm.com/api"
H = {"Authorization": f"Bearer {os.environ['GF_TOKEN']}"}

r = requests.post(f"{API}/instances", headers=H, json={
    "gpu": "h200", "count": 4, "template": "custom",
    "image": "nvidia/cuda:12.4.1-devel-ubuntu22.04", "disk": 200,
    "cmd": "pip install -q torch && python /workspace/train.py",
})
if not r.ok:
    raise SystemExit(f"{r.status_code} {r.json()['code']}: {r.json()['error']}")
print("server", r.json()["id"])
Antwort · 200
{
  "ok": true,
  "id": 1234,
  "status": "provisioning"
}

Server auflisten

GET/api/instances

Ihre Server, die neuesten zuerst, bis zu 100. Standardmäßig: laufende, startende und in den letzten 7 Tagen gestoppte.

Query-Parameter

ParameterTypBeschreibung
statusoptionalstringprovisioning, running oder stopped: nur Server in diesem Zustand.

Jedes Element von instances hat dieselbe Form wie die Antwort von GET /api/instances/{id}.

Fehler

  • 401Falscher oder widerrufener Token
Anfrage
import os, requests

API = "https://vramfarm.com/api"
H = {"Authorization": f"Bearer {os.environ['GF_TOKEN']}"}

r = requests.get(f"{API}/instances", headers=H, params={"status": "running"})
for s in r.json()["instances"]:
    print(s["id"], s["gpu_name"], s["cost_eur"], "EUR")
Antwort · 200
{
  "instances": [
    { "id": 1234, "status": "running", "gpu": "h200", "gpu_count": 4, "cost_eur": 0.55, "...": "..." }
  ]
}

Server und Zugang

GET/api/instances/{id}

Der Zustand eines Servers. Sobald status gleich running ist, enthält access SSH, Jupyter und die Adresse der App.

Pfadparameter

ParameterTypBeschreibung
idPflichtintegerid aus der Antwort beim Start
Felder der Antwort
statusstringprovisioning: wird vorbereitet; running: läuft und wird abgerechnet; stopped: gestoppt
stage, stage_notestring | nullNur während provisioning: die Phase (zum Beispiel pick, loading) und was gerade passiert, in der Sprache Ihres Kontos
gpu, gpu_name, gpu_countstring, integerModell und Anzahl der Karten
template, imagestringTemplate und Image (bei custom)
disk_gbintegerFestplatte, GB
price_eur_hournumberStundenpreis für den ganzen Server, EUR
cost_eurnumberFür diesen Start berechnet, EUR; bei einem laufenden Server bis zur aktuellen Minute
traffic_eurnumberFür Traffic berechnet, EUR
specsobject | nullDaten der Maschine
access.sshobject | nullhost, port, user und ein fertiger command
access.jupyterstring | nullJupyter-Link mit Token
access.appstring | nullAdresse der App bei ComfyUI und vLLM; bei custom, wenn das Image einen eigenen Port öffnet. Mehr unter Apps auf dem Server
access.workdirstringArbeitsordner, /workspace
errorstring | nullWarum der Server von selbst gestoppt wurde: Das Image ließ sich nicht herunterladen, das Guthaben war aufgebraucht
created_at, started_at, stopped_atstring | nullZeit in ISO 8601, UTC

access ist nur bei einem laufenden Server gefüllt. Der SSH-Schlüssel ist derjenige aus Ihren Dashboard-Einstellungen. Startet eine Maschine nicht, nehmen wir kostenlos eine andere; die id des Servers bleibt gleich.

Mit dem Server arbeiten
ssh -p 31001 root@vramfarm.com nvidia-smi
scp -P 31001 root@vramfarm.com:/workspace/out.ckpt ./

Fehler

  • 404Kein Server mit dieser id, oder er gehört nicht Ihnen
Anfrage
import os, requests

API = "https://vramfarm.com/api"
H = {"Authorization": f"Bearer {os.environ['GF_TOKEN']}"}

s = requests.get(f"{API}/instances/1234", headers=H).json()
if s["status"] == "running":
    print(s["access"]["ssh"]["command"])
else:
    print(s["status"], s["stage_note"] or s["error"])
Antwort · 200
{
  "id": 1234,
  "status": "running",
  "stage": null,
  "stage_note": null,
  "gpu": "h200",
  "gpu_name": "H200",
  "gpu_count": 4,
  "template": "custom",
  "image": "nvidia/cuda:12.4.1-devel-ubuntu22.04",
  "disk_gb": 200,
  "price_eur_hour": 33.16,
  "cost_eur": 0.55,
  "traffic_eur": 0,
  "specs": {
    "vram_gb": 141, "cpu": "AMD EPYC 9354", "cpu_cores": 64, "ram_gb": 512,
    "country": "DE", "cuda": 12.8, "net_down_mbps": 8000, "net_up_mbps": 8000
  },
  "access": {
    "ssh": {
      "host": "vramfarm.com",
      "port": 31001,
      "user": "root",
      "command": "ssh -p 31001 root@vramfarm.com"
    },
    "jupyter": "https://u.vramfarm.com/api/j/…/lab?token=…",
    "app": null,
    "workdir": "/workspace"
  },
  "error": null,
  "created_at": "2026-10-21T10:00:00.000Z",
  "started_at": "2026-10-21T10:04:12.000Z",
  "stopped_at": null
}

Server stoppen

POST/api/instances/stop

Stoppt den Server; die Abrechnung endet sofort. Die Festplatte des Servers wird gelöscht; den Arbeitsordner können Sie speichern.

Request-Body, JSON

ParameterTypBeschreibung
idPflichtintegerid des Servers
saveoptionalbooleantrue: zuerst /workspace speichern, dann stoppen. Funktioniert nicht bei custom.
forceoptionalbooleantrue: sofort stoppen, auch wenn der Ordner noch gespeichert wird. Das Speichern wird abgebrochen.

Einen bereits gestoppten Server zu stoppen liefert {"ok":true,"already":true}. Das ist kein Fehler, Sie können den Aufruf also in finally oder in einen trap beim Beenden des Skripts setzen.

Mit "save": true kommt die Antwort {"ok":true,"saving":true} sofort zurück, und der Server speichert den Ordner und stoppt von selbst, meist innerhalb weniger Minuten. Der Speicher kostet 0,03 € pro GB und Monat, täglich abgerechnet. Ihr nächster Server bekommt den Ordner automatisch, außer Sie übergeben "ws_restore": false.

Fehler

  • 404Kein Server mit dieser id, oder er gehört nicht Ihnen
  • 409Der Ordner wird noch gespeichert; die Antwort enthält "saving": true. Warten Sie oder übergeben Sie "force": true
Anfrage
import os, requests

API = "https://vramfarm.com/api"
H = {"Authorization": f"Bearer {os.environ['GF_TOKEN']}"}

r = requests.post(f"{API}/instances/stop", headers=H, json={"id": 1234})
print(r.json())
Antwort · 200
{
  "ok": true
}

Konto

Konto

GET/api/account

Guthaben und Startbereitschaft. Praktisch, um vor dem Start zu prüfen, ob Ihre E-Mail-Adresse bestätigt und ein SSH-Schlüssel hinterlegt ist.

Keine Parameter.

emailstringE-Mail-Adresse des Kontos
verifiedbooleanE-Mail-Adresse bestätigt. Ohne Bestätigung liefert ein Start 403
balance_eurnumberGuthaben, EUR
ssh_key_setbooleanSSH-Schlüssel hinterlegt. Ohne Schlüssel startet der Server trotzdem, aber Sie kommen nur über Jupyter hinein
active_instancesintegerWie viele Server gerade starten oder laufen
max_active_instancesintegerWie viele Sie gleichzeitig betreiben können

Fehler

  • 401Falscher oder widerrufener Token, oder das Konto ist gesperrt
Anfrage
import os, requests

API = "https://vramfarm.com/api"
H = {"Authorization": f"Bearer {os.environ['GF_TOKEN']}"}

acc = requests.get(f"{API}/account", headers=H).json()
assert acc["verified"] and acc["ssh_key_set"], acc
print(acc["balance_eur"], "EUR")
Antwort · 200
{
  "email": "you@example.com",
  "verified": true,
  "balance_eur": 150.0,
  "ssh_key_set": true,
  "active_instances": 0,
  "max_active_instances": 4
}

Dienst

Dienststatus

GET/api/health

Prüft, ob die API erreichbar ist. Kein Token nötig.

Keine Parameter.

Bei einer Störung lautet die Antwort 503 mit einem kurzen Grund in why, zum Beispiel {"ok":false,"why":"…"}.

Fehler

  • 503Der Dienst funktioniert nicht vollständig; der Grund steht in why
Anfrage
import requests

r = requests.get("https://vramfarm.com/api/health", timeout=10)
print(r.status_code, r.json())
Antwort · 200
{
  "ok": true,
  "status": "ok"
}

Apps auf dem Server per API

ComfyUI, die Apps für Text zu Sprache, der Chat und vLLM haben jeweils eine eigene API. Damit erzeugen Sie Bilder, Audio und Text aus einem Skript, ohne die Oberfläche zu öffnen. Ihren VRAMfarm-Token brauchen diese Apps nicht, und er wird nie an sie gesendet.

So finden Sie die Adresse der App:

  • ComfyUI und vLLM: das Feld access.app in GET /api/instances/{id}, etwa https://u.vramfarm.com/api/a/<key>/. Bei vLLM endet sie bereits auf v1.
  • Chat und Text zu Sprache: Eine Adresse wie http://<host>:<port> steht auf der Server-Karte im Dashboard; in access.app ist sie nicht enthalten. Aus einem Skript ist ein SSH-Tunnel zuverlässiger: Er funktioniert immer, wenn SSH funktioniert.
  • Eigenes Image (custom): access.app ist gefüllt, wenn der Container einen anderen Port als 22, 8080 und 8888 öffnet.
SSH-Tunnel
# SSH port from access.ssh.port; -N: tunnel only, no shell
ssh -p 31001 root@vramfarm.com -N -L 11434:127.0.0.1:11434

Lassen Sie den Tunnel offen, solange Ihr Skript läuft: Anfragen an localhost:11434 gehen an den Server. Für Text zu Sprache nehmen Sie Port 7860 (-L 7860:127.0.0.1:7860), für ComfyUI 8188, für vLLM 8000. Die App startet 5–10 Minuten nach running; bis dahin liefert die Adresse 502 oder antwortet nicht.

ComfyUI

Templates comfyui und comfy-*. Bauen Sie einen Workflow in der Oberfläche und speichern Sie ihn über Workflow → Export (API) als workflow_api.json. Das Skript ändert dann den Prompt-Text im Workflow, sendet ihn an /prompt, wartet auf das Ergebnis in /history/{prompt_id} und lädt die Bilder über /view herunter.

import json, time, requests

APP = "https://u.vramfarm.com/api/a/<key>/"                                   # access.app of the server
wf = json.load(open("workflow_api.json"))        # Workflow → Export (API) in ComfyUI
wf["6"]["inputs"]["text"] = "a cat in a spacesuit, photo"  # node number from your file

pid = requests.post(APP + "prompt", json={"prompt": wf}).json()["prompt_id"]
while pid not in (h := requests.get(APP + f"history/{pid}").json()):
    time.sleep(2)

for node in h[pid]["outputs"].values():
    for img in node.get("images", []):
        data = requests.get(APP + "view", params=img).content  # filename, subfolder, type
        open(img["filename"], "wb").write(data)

Text zu Sprache und andere Gradio-Apps

Die Templates tts-qwen3, tts-voxcpm und tts-chatterbox basieren auf Gradio. Unten auf der Seite der App gibt es den Link „Use via API“ mit den Methoden, ihren Parametern und fertigen Beispielen. Die Methodennamen unterscheiden sich je nach App. Ersetzen Sie daher /generate im Beispiel durch den Namen aus „Use via API“ oder aus view_api().

# pip install gradio_client
from gradio_client import Client

client = Client("http://localhost:7860/")   # through an SSH tunnel or the address from the dashboard
client.view_api()                           # list of methods and their parameters

# method name and argument order: from view_api() or "Use via API"
audio_path = client.predict("Hello! This is a speech test.", api_name="/generate")
print(audio_path)                           # the result file on your computer

Chat: Ollama und Open WebUI

Templates chat, chat-pro und chat-mimo: Open WebUI läuft auf Ollama. Aus einem Skript sprechen Sie Ollama einfacher direkt an. Es lauscht nur innerhalb des Servers auf 127.0.0.1:11434, Sie brauchen also einen SSH-Tunnel wie im Beispiel oben. Das Modell wird nach dem Start heruntergeladen; bis es geladen ist, meldet Ollama, dass das Modell fehlt.

import requests

r = requests.post("http://localhost:11434/api/chat", json={
    "model": "qwen3:8b",          # chat-pro uses qwen3:32b
    "messages": [{"role": "user", "content": "In one sentence: what is CUDA?"}],
    "stream": False,
})
print(r.json()["message"]["content"])

Ollama versteht unter http://localhost:11434/v1/chat/completions auch das OpenAI-Format, OpenAI-Bibliotheken funktionieren also. Auch Open WebUI hat eine eigene API; den Schlüssel dafür erstellen Sie in den Einstellungen von Open WebUI.

vLLM

Das Template vllm startet einen OpenAI-kompatiblen Server mit Qwen/Qwen2.5-7B-Instruct. Die Adresse ist access.app, sie endet bereits auf /v1. Der Schlüssel wird nicht geprüft, die OpenAI-Bibliothek verlangt aber einen nicht leeren, übergeben Sie also einen beliebigen. Die Modellliste gibt es unter GET /v1/models.

# pip install openai
from openai import OpenAI

client = OpenAI(base_url="https://u.vramfarm.com/api/a/<key>/v1",  # access.app
                api_key="EMPTY")                                    # no key needed
r = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    messages=[{"role": "user", "content": "Write a haiku about a graphics card"}],
)
print(r.choices[0].message.content)

Sie brauchen einen Token? Registrieren Sie sich, bestätigen Sie Ihre E-Mail-Adresse und erstellen Sie einen Token in den Dashboard-Einstellungen. Wenn etwas nicht zu dieser Seite passt oder Sie ein höheres Limit brauchen, schreiben Sie uns.