Control API-Referenz
Die lokale HTTP-API, die SimpliGen auf deinem Gerät bereitstellt, für die Erstellung benutzerdefinierter Integrationen und die Ausführung von Generierungen im Headless-Modus.
SimpliGen führt eine kleine HTTP Control API auf deinem Gerät aus, während die App offen ist. Es ist dieselbe API, mit der der MCP-Server kommuniziert, direkt verfügbar gemacht, sodass du SimpliGen von deinen eigenen Scripts, Services oder Agenten aus steuern kannst, auch mit der App minimiert in der Taskleiste.
MCP vs. Control API
Wenn du möchtest, dass ein KI-Agent (Claude, Codex usw.) SimpliGen nutzt, richte stattdessen den MCP-Server ein, der diese API umhüllt. Verwende die Control API direkt, wenn du eine benutzerdefinierte Integration in jeder beliebigen Sprache schreibst.
Basis-URL und Erkennung
Der Server bindet sich nur an Loopback und hat standardmäßig:
http://127.0.0.1:48199Wenn dieser Port verwendet wird, nutzt SimpliGen einen vom Betriebssystem zugewiesenen Port. Der aktuelle Port (und die API-Version) wird immer in eine Erkennungsdatei im Benutzerverzeichnis der App geschrieben:
# Windows
%APPDATA%\simpligen\agent-api.json
# macOS
~/Library/Application Support/simpligen/agent-api.json
# Linux
~/.config/simpligen/agent-api.json{ "port": 48199, "version": 1 }Lies diese Datei, um den aktiven Port zu finden, anstatt 48199 fest zu codieren.
Anforderungen
Die Control API läuft nur, wenn die App offen ist und die Maschine berechtigt ist, auf Agenten zuzugreifen (es ist Teil deiner Lizenz). Anfragen werden nur beantwortet, wenn der Host-Header ein Loopback-Alias ist, alles andere erhält 403 forbidden_host (ein DNS-Rebinding-Schutz).
Authentifizierung
Jeder Endpunkt außer GET /health benötigt ein Pairing-Token im Authorization-Header:
Authorization: Bearer sg-agent-xxxxxxxx...Erstelle ein Token in der App unter Einstellungen → Agent verbinden (siehe Agent verbinden). Das rohe Token wird einmal angezeigt; nur ein Hash wird gespeichert. Jedes Token kann eine optionale Ausgabenbegrenzung für Cloud-Generierungen haben. Das Widerrufen eines Tokens in der App wird sofort wirksam.
Ein fehlender oder ungültiger Token gibt 401 unauthorized zurück.
Konventionen
- Anfragen: JSON-Bodies (
Content-Type: application/json), bis zu 50 MB. - Antworten: immer JSON.
- Fehler: Nicht-2xx-Antworten haben die Form
{ "errorCode": "...", "message": "..." }. - IDs: Presets werden mit
presetId(+optionalespackId) adressiert; Jobs mitjobId.
Ein minimaler authentifizierter Aufruf:
TOKEN="sg-agent-..."
curl -s http://127.0.0.1:48199/status -H "Authorization: Bearer $TOKEN"Gesundheitsprüfung
GET /health
Liveness Probe. Keine Authentifizierung erforderlich.
{ "ok": true, "name": "simpligen", "version": 1 }Fähigkeiten
GET /capabilities
Listet jeden Preset auf, mit dem du generieren kannst, einen Eintrag pro (preset, mediaType), mit seinen Eingaben, Optionen, lokale Bereitschaft und Cloud-Berechtigung/Kosten.
{
"capabilities": [
{
"packId": "local-core-pack",
"presetId": "z-image-turbo",
"mediaType": "image",
"name": "Z-Image Turbo",
"description": "Ultra-fast, high-quality images in seconds",
"apiProvider": null,
"inputs": {
"acceptsPrompt": true,
"requiresPrompt": true,
"requiresImage": false,
"acceptsReferenceImages": null,
"acceptsVideo": false,
"acceptsAudio": false,
"acceptsReferenceVideos": false,
"acceptsReferenceAudios": false,
"supportsLoras": true
},
"options": {
"steps": null,
"cfg": null,
"duration": null,
"resolution": null,
"aspectRatio": ["1:1", "3:4", "4:3", "9:16", "16:9"]
},
"cloudAliasTo": null,
"localReady": true,
"cloudEligible": true,
"cloudCost": 4
}
]
}| Feld | Bedeutung |
|---|---|
localReady | Alle Modelldateien sind installiert; der Preset kann jetzt lokal ausgeführt werden. |
cloudEligible | Der Preset kann auf SimpliGen Cloud ausgeführt werden. |
cloudCost | Ungefähre Kreditkosten für einen Cloud-Run (null wenn nicht berechtigt). |
apiProvider | Nicht-null für externe API-Presets (z. B. OpenAI, Google), die die Control API nicht verteilen kann. |
inputs / options | Was der Preset akzeptiert und die Optionsbereiche/Seitenverhältnisse, die du an POST /generate übergeben kannst. steps/cfg sind nur nicht-null für Presets, die erweiterte Steuerelemente bereitstellen. |
inputs.requiresPrompt | false für Presets, deren Anweisungen eingebaut sind (Ausschnitte, Kopf- oder Outfitwechsel, Upscales): ein leerer prompt ist gültig, und jeder von dir gesendete Text wird als zusätzliche Notizen hinzugefügt. |
Status
GET /status
{
"engineRunning": true,
"engineVersion": "v0.26.0",
"cloudConnected": true,
"creditBalance": 1280,
"activeProject": { "id": "default", "name": "My Project" },
"characters": { "enabled": true, "base": 1, "edit": 1, "i2v": 1, "enhancePresets": 2 }
}POST /engine/start
Startet die lokale Engine, wenn sie nicht bereits läuft. Kein Body erforderlich.
{ "engineRunning": true, "engineVersion": "v0.37.0", "engineStarting": false }Ein Kaltstart dauert länger als die Anfrage wartet. In diesem Fall ist die Antwort 202 mit engineStarting: true und die Engine startet weiter. Daher Polling durchführen GET /status bis engineRunning wahr ist.
Das Starten einer bereits laufenden Engine gibt 200 mit alreadyRunning: true zurück und ändert nichts. Wenn keine Engine installiert ist, ist die Antwort 409 engine_not_installed: Das Installieren einer ist ein Multi-Gigabyte-Download und bleibt eine Aufgabe für die App, nicht für die API. Eine Maschine, auf der die Engine nicht ausgeführt werden kann, antwortet 409 engine_unsupported_hardware, ein erneutes Versuchen behebt dies nicht.
POST /engine/stop
Stoppt die lokale Engine und gibt ihren VRAM frei. Cloud-Generierungen sind nicht betroffen. Das Stoppen einer bereits heruntergefahrenen Engine ist ein Erfolg.
POST /engine/restart
Stoppt und startet es erneut, für eine fehlerhafte Engine oder nach einer benutzerdefinierten Node wurde installiert oder entfernt. Gleiches 202-Verhalten wie Start, wenn der Boot die Anfrage übersteigt.
Projekte
Projekte sind die Container, die Generierungen enthalten.
GET /projects
{ "projects": [ { "id": "default", "name": "My Project", "slug": "my-project" } ] }POST /projects
{ "name": "Campaign assets" }Gibt 201 mit { "project": { ... } } zurück. name ist erforderlich (ansonsten 400 invalid_options).
Uploads
Eingaben (Quellbilder, Referenzbilder, Quellvideos) werden niemals als lokale Pfade übergeben. Lade die Bytes zuerst hoch und übergebe das zurückgegebene Handle an POST /generate.
POST /uploads
{ "filename": "ref.png", "dataBase64": "<base64 of the file bytes>" }{ "handle": "a1b2c3d4.png", "sizeBytes": 51234 }Max Upload ist 100 MB (413 asset_too_large). Nicht unterstützte Dateitypen geben 400 unsupported_file_type zurück.
Generieren
POST /generate
Reiht eine Generierung ein und gibt sofort einen jobId zurück. Polling durchführen GET /jobs/:id (siehe Jobs) für das Ergebnis.
{
"presetId": "z-image-turbo",
"packId": "local-core-pack",
"mediaType": "image",
"prompt": "a red fox in the snow, cinematic",
"backend": "auto",
"project": "default",
"image": "a1b2c3d4.png",
"referenceImages": [{ "handle": "e5f6.png", "label": "style" }],
"loras": [
{ "name": "RoomLora", "weight": 0.85 },
{ "name": "Mia", "weight": 0.75 }
],
"options": { "aspectRatio": "16:9", "steps": 8, "negativePrompt": "blurry, watermark" }
}| Feld | Erforderlich | Notizen |
|---|---|---|
presetId | ja | Von GET /capabilities. |
mediaType | ja | "image" oder "video". |
packId | nein | Falls angegeben, muss dem Pack des Presets entsprechen. |
prompt | bedingt | Erforderlich, wenn der Preset nicht inputs.requiresPrompt: false meldet. Diese Presets haben ihre Anweisungen eingebaut: Sende "", um sie unverändert auszuführen, oder füge Text hinzu, um zusätzliche Notizen zu übergeben. |
backend | nein | "auto" (Standard), "local" oder "cloud". Auto bevorzugt lokal, wenn installiert, sonst Cloud, wenn verbunden. |
image | bedingt | Upload Handle. Erforderlich für Image-to-X-Presets (inputs.requiresImage). |
video | bedingt | Upload Handle, für Video-Input-Presets. |
referenceImages | bedingt | Array von Handles oder { handle, label }, für Referenzbild-Presets. |
audio | bedingt | Upload Handle, für Audio-gesteuerte Presets (Lip-Sync, Audio-zu-Video). Erforderlich, wenn der Preset acceptsAudio meldet, ansonsten wird der Job mit needs_audio abgelehnt. |
audioStartSeconds | nein | Wo in der Spur beginnen, in Sekunden. Auch unter options akzeptiert. |
referenceVideos | bedingt | Array von Handles oder { handle, soundtrackMode, durationSeconds }, für Referenz-Clip-Presets. |
referenceAudios | bedingt | Array von Handles oder { handle, durationSeconds }, für Referenzsound-Presets. |
loras | nein | Array von { name, weight } zum Anwenden, für Presets, bei denen inputs.supportsLoras true ist. name entspricht einem LoRA-Anzeigenamen (oder Dateinamen) von GET /loras; weight verfällt auf die Standard-Stärke des LoRA. Unbekannte Namen geben 400 unknown_lora zurück. Nur lokales Backend für jetzt. |
project | nein | Projekt-id oder slug. Verfällt auf das aktive Projekt. |
options.aspectRatio | nein | Muss eines der unterstützten Seitenverhältnisse des Presets sein. |
options.steps / options.cfg | nein | Innerhalb der beworbenen Bereiche des Presets. |
options.negativePrompt | nein | Negativer Prompt (der negative Wert der UI-Optionen des Advanced Options). Auch auf oberster Ebene als negativePrompt akzeptiert. |
options.durationSeconds | nein | Videodauer. |
options.resolution | nein | Auflösungs-Tier-Label. |
{ "jobId": "gen_abc123", "backend": "local", "status": "queued" }Für einen Cloud-Job enthält die Antwort auch "cloudCost": <credits>.
Backends
Externe API-Presets (bei denen apiProvider nicht-null ist, z. B. GPT Image 2, Veo) können hier nicht verteilt werden, du erhältst 400 unsupported_backend. Verwende einen lokalen oder SimpliGen Cloud Preset. Cloud erfordert ein verbundenes Konto (400 cloud_not_connected); lokal erfordert die installierten Modelle (400 preset_not_installed, bereite sie zuerst vor).
GET /loras
Listet die installierten LoRAs des Benutzers auf, damit Agenten entdecken können, was sie in das loras-Array von POST /generate eingeben sollen. Abgleich nach name (der Anzeigename).
{
"loras": [
{ "name": "RoomLora", "filename": "RoomLora_000002400.safetensors", "baseModel": "flux", "triggerWords": "a room", "defaultStrength": 0.9 },
{ "name": "Mia", "filename": "mia_v2.safetensors", "baseModel": "flux", "triggerWords": "mia", "defaultStrength": 1.0 }
]
}Übergebe das LoRA, wo es zum Basis-Modell des Presets passt (baseModel), und verwende seine eigenen Trigger-Wörter in deinem Prompt, damit es aktiviert wird.
Jobs
GET /jobs/:id
{
"job": {
"jobId": "gen_abc123",
"status": "completed",
"backend": "local",
"mediaType": "image",
"presetId": "z-image-turbo",
"projectId": "default",
"resultUrl": "local-file:///C:/Users/you/.../output.png",
"resultPath": "C:/Users/you/.../output.png",
"errorMessage": null,
"createdAt": "2026-06-25T20:00:00.000Z",
"completedAt": "2026-06-25T20:00:08.000Z"
}
}status ist einer von queued, processing, completed, failed. Bei Erfolg ist resultPath der dekodierte lokale Dateipfad; bei Fehler erklärt errorMessage warum. Unbekannte ID gibt 404 job_not_found zurück.
GET /jobs
Gibt die 25 letzten Jobs als { "jobs": [ ...job... ] } zurück.
POST /jobs/:id/cancel
Bricht einen in die Warteschlange eingereihten/laufenden Job ab. Gibt { "jobId", "status", "note?" } zurück. Ein Cloud-Job, der bereits unterwegs ist, kann möglicherweise noch auf dem Server abgeschlossen werden (wird in note vermerkt).
Vorbereitung von Presets
Lokale Presets laden ihre Modelldateien beim ersten Gebrauch herunter. Du kannst sie im Voraus vorbereiten.
POST /presets/prepare
{ "presetId": "z-image-turbo", "mediaType": "image" }Gibt 200 { "status": "already_installed" } oder 202 { "status": "started" } zurück (Download läuft im Hintergrund).
GET /presets/prepare
Gibt laufende Downloads zurück: { "downloads": [ ... ] }. Polling durchführen, oder GET /capabilities (watch localReady), bis der Preset bereit ist.
Zeichen
Character Studio ist auch skriptbar. Zeichen sind nur lokal (Cloud wird abgelehnt). Siehe Characters für die Konzepte.
| Endpunkt | Zweck |
|---|---|
GET /characters | Zeichen auflisten. |
GET /characters/:id | Ein Zeichen abrufen. |
GET /character-presets | Installierte Zeichen-Presets (Base, Edit, I2V). |
GET /character-features | Verfügbare Identitäts-/Erscheinungsmerkmalsoptionen. |
POST /characters | Erstelle ein Zeichen (mode: "generate" aus einer Beschreibung, oder "upload" aus einem hochgeladenen Basis-Image-Handle). |
POST /characters/:id/generate-image | Generiere ein Bild des Charakters ({ prompt, aspect?, count?, presetId? }). |
POST /characters/:id/generate-frame | Generiere einen einzelnen Video-Start-Frame. |
POST /characters/:id/animate | Animiere das Zeichen in ein Video. |
POST /characters/:id/preset | Setze den Standard-Preset des Charakters. |
POST /characters/:id/enhance | Skaliere/verbessere ein Zeichen-Asset. |
Alle Generierungs-Endpunkte geben einen jobId zurück, den du über GET /jobs/:id polisierst, genau wie POST /generate.
Rezepte
Verfasse Multi-Schritt-Rezepte (Flows) aus Packs und Presets. Entdecke die Bausteine, komponiere aus einer Spezifikation auf hoher Ebene, veröffentliche dann optional.
| Endpunkt | Zweck |
|---|---|
GET /recipe-blocks | Einstiegspunkte + jeder Preset verwendbar als Schritt, mit seinem Port-Vertrag. |
POST /recipes/validate | Dry-run einer spec (Zusammensetzen+Validieren) oder einer config, kein Speichern. Gibt validation zurück. |
POST /recipes | Komponiere aus einer spec und speichere einen Entwurf. Gibt { recipeId, valid, errors, config } zurück. |
GET /recipes | Liste jeden Rezept auf diesem Gerät (aus dem Store installiert oder hier verfasst) mit seinen inputs (Schlüssel, Art, Label, erforderlich, Optionen) und Schrittanzahl. |
GET /recipes/:id | Hole ein Rezept, seine vollständige Config, seine inputs und readiness (pro Schritt: welcher Preset es läuft und ob es lokal installiert ist). |
POST /recipes/:id/run | Führe ein Rezept aus. Body: { inputs: { key: value }, engine?: "local" | "cloud" | "auto" }. Subject-Eingaben nehmen eine Charakter- oder Produkt-ID, Image/Video/Audio-Eingaben nehmen Upload-Handles, alles andere nimmt einfache Werte. Gibt { runId, status: "running", engine, steps, cloudCost? } zurück. Cloud-Runs werden im Voraus berechnet und zählen gegen die Ausgabenbegrenzung des Tokens. |
GET /recipes/:id/runs | Aktuelle Läufe eines Rezepts, neueste zuerst. |
GET /recipe-runs/:id | Status eines Laufs: status (läuft, abgeschlossen, fehlgeschlagen, abgebrochen), steps (jeder mit Status, Job-ID und Ergebnispfad) und resultPath, sobald der letzte Media-Schritt abgeschlossen ist. |
POST /recipe-runs/:id/cancel | Stoppe einen Lauf. Keine weiteren Schritte starten; ein lokaler laufender Schritt wird unterbrochen. |
POST /recipes/:id/publish | Sende zum Creator Marketplace (benötigt ein verbundenes Konto). |
Produkte und Subjekte
Eine subject-Eingabe eines Rezepts nimmt entweder ein Zeichen oder ein Produkt. Produkte sind der andere Subjekttyp: ein benanntes Ding mit einem Basisfoto, verwendet von Product Studio und UGC-Rezepten.
| Endpunkt | Zweck |
|---|---|
GET /subjects | Jedes Subjekt, das ein Rezept nehmen kann: Zeichen und Produkte (id, type, name, status). |
GET /products | Produkte auflisten. |
GET /products/:id | Ein Produkt abrufen. |
POST /products | Erstelle ein Produkt aus einem hochgeladenen Foto: { name, image: <upload handle>, description?, category? }. Die Beschreibung und Kategorie werden in Rezept-Prompts eingewebt. Gibt { productId, product } zurück. |
DELETE /products/:id | Entferne ein Produkt und sein Foto. |
Eine spec ist eine Beschreibung auf hoher Ebene; die App verbindet Ports automatisch, die Schritt-für-Schritt-Media-Kette und einen Prompt-Input pro Schritt, dann validiert.
{
"spec": {
"name": "Product to spinning video",
"category": "product",
"steps": [
{ "preset": "krea2-pack:krea2-turbo" },
{ "preset": "wan-2.2-video-pack:wan-2.2-i2v" }
]
}
}{
"recipeId": "b1f2…",
"valid": true,
"errors": [],
"config": { "blocks": [ "…" ], "inputs": [ "…" ], "output": { "from": "n2.video" } }
}Zusammensetzen und Speichern benötigen kein Creator-Konto. POST /recipes/:id/publish benötigt ein verbundenes Konto und gibt not_connected (mit needsConnect: true) zurück, bis der Benutzer ein in der App verbindet; der gleiche Entwurf veröffentlicht dann unverändert. Jeder Preset, den das Rezept verwendet, muss zu einem verteilbaren First-Party-Pack gehören.
Ausgabenbegrenzungen
Wenn ein Token eine Ausgabenbegrenzung hat, werden Cloud-Generierungen vor dem Versand berechnet und abgelehnt, wenn sie die verbleibende Zuteilung überschreiten würden (402 exceeds_spend_cap). Wenn die Kosten nicht bestimmt werden können (Cloud-Status nicht verfügbar), schlägt ein begrenztes Token mit 503 cost_unknown fehl. Lokale Generierungen sind immer frei von Kreditkosten.
Ein vollständiger Flow
BASE=http://127.0.0.1:48199
AUTH="Authorization: Bearer sg-agent-..."
# 1. Pick a ready preset
curl -s $BASE/capabilities -H "$AUTH"
# 2. Generate
JOB=$(curl -s $BASE/generate -H "$AUTH" -H 'Content-Type: application/json' \
-d '{"presetId":"z-image-turbo","mediaType":"image","prompt":"a red fox in the snow","options":{"aspectRatio":"16:9"}}' \
| jq -r .jobId)
# 3. Poll until done, then read resultPath
curl -s $BASE/jobs/$JOB -H "$AUTH" | jq '.job | {status, resultPath, errorMessage}'Fehlercodes
| HTTP | errorCode | Wann |
|---|---|---|
| 400 | invalid_json | Body ist kein gültiges JSON. |
| 400 | invalid_options | Ein erforderliches Feld fehlt oder ist falsch formatiert. |
| 400 | invalid_preset | Preset/Pack/MediaType-Mismatch. |
| 400 | needs_* | Eine erforderliche Eingabe (Prompt, Bild, Referenzen) fehlt. |
| 400 | invalid_handle | Eine Eingabe war kein gültiges Upload-Handle. |
| 400 | unsupported_backend | Preset läuft auf einer externen API. |
| 400 | preset_not_installed | Lokales Backend ausgewählt, aber Modelle sind nicht installiert. |
| 400 | cloud_not_connected | Cloud Backend ausgewählt, aber kein Konto verbunden. |
| 401 | unauthorized | Token fehlt oder ungültig. |
| 402 | exceeds_spend_cap | Cloud-Kosten überschreiten die Ausgabenbegrenzung des Tokens. |
| 403 | forbidden_host | Non-Loopback Host-Header. |
| 404 | not_found / invalid_preset / job_not_found | Unbekannte Route, Preset oder Job. |
| 413 | asset_too_large | Upload über 100 MB. |
| 503 | cost_unknown | Begrenztes Token; Cloud-Kosten konnten nicht bestimmt werden. |
| 500 | internal_error | Unerwarteter Serverfehler. |