Pro API: Guthaben, Limits und trainierte Charaktere

Zwei Leseendpunkte, die unabhängig von den Berechtigungen des Keys immer zugänglich sind, sowie das Aktivitätsprotokoll in der App.

Guthaben und Limits

GET /credits

json
{ "balance": 1830, "licenseId": "lic_...", "key": "k_1a2b3c4d",
  "limits": { "concurrent": 2, "perMinute": 60, "perDay": 0 }, "running": 1,
  "buy_url": "https://tendre.ai/credits?license=lic_..." }
FeldBedeutung
balanceVerbleibendes Guthaben. null, wenn das Guthaben unbekannt ist (Testumgebung).
licenseIdDie Lizenz, zu der dieser Key gehört.
keyDer öffentliche Bezeichner des Keys, sicher zum Loggen. Niemals das Geheimnis selbst.
limits.concurrentGleichzeitig laufende Renders, standardmäßig 2.
limits.perMinuteAnfragen pro Minute, standardmäßig 60.
limits.perDayTägliches Guthaben-Limit, das du für den Key festgelegt hast. 0 bedeutet kein Limit.
runningRenders dieses Keys, die noch auf Abholung warten.
buy_urlDie Seite zum Kauf von Credits für deine Lizenz, per Karte oder Krypto.

Dies ist der günstigste Aufruf der API und der richtige, um zu prüfen, ob ein Key funktioniert.

Credits mit deiner gespeicherten Karte kaufen

POST /credits/purchase

json
{ "pack": "m" }

pack ist eine Paket-ID (s, m, l, xl, xxl oder xxxl) oder "c25000" für eine freie Menge über dem größten Paket. Die Zahlung geht auf die Karte, die im automatischen Aufladen deiner Kontoseite gespeichert ist, nur wenn du dort deinem Agenten das Kaufen erlaubt hast, innerhalb des monatlichen Limits, das du dort festgelegt hast (automatische Aufladungen eingeschlossen). Jeder Kauf wird per E-Mail bestätigt. Immer nur ein Kauf gleichzeitig.

Die Antwort ist 200 { credits, eur, balance }. Jede Ablehnung enthält buy_url, den normalen Kauflink, den du stattdessen nutzt: 402 confirmation_required (deine Bank verlangt deine Bestätigung) oder payment_declined; 409 agent_not_allowed, no_saved_card, monthly_cap_reached, topup_in_progress oder purchase_in_progress; 400 unknown_pack. Bei 503 payment_unavailable wissen wir nicht, ob die Belastung erfolgt ist: nicht sofort erneut versuchen, eine erfolgte Belastung wird gutgeschrieben.

Trainierte Charaktere

Das sind die Charaktere, die als LoRA trainiert wurden, für Bilder und normale Videos. Die Charaktere von Multi-Ref Video, sieben Ansichten aus einem einzigen Foto, sind etwas anderes: siehe Characters.

GET /loras

json
{ "image": [ { "name": "megan_krea2", "trigger": "megan", "base": "krea2", "size": 0 } ],
  "video": [ { "name": "megan_ltx", "trigger": "megan", "size": 0 } ] }

Übergib name als lora, nimm ihn für Bilder aus der image-Liste und für Videos aus der video-Liste, und füge den trigger in den Prompt ein, sonst erscheint der Charakter nicht. Ein Charakter, der nicht zum Account gehört, antwortet mit 403 unknown_lora.

Eigene LoRA hochladen

POST /loras/upload

Eine .safetensors-Datei, die du bereits hast, anderswo trainiert oder auf deinem eigenen Server gespeichert, wird in den Speicherplatz des Accounts geladen und ist über lora nutzbar, genau wie ein in der App trainierter Charakter. Es gibt zwei Wege: auf einmal bis 90 MB, oder in Teilen darüber hinaus. Eine LoRA wiegt üblicherweise 200 bis 500 MB, also ist der zweite Weg der Normalfall. Die Obergrenze liegt in beiden Fällen bei 800 MB.

Auf einmal: ein roher Body (application/octet-stream, Content-Length erforderlich), Parameter in der URL.

Ab 100 MB erreicht die Anfrage die API nicht mehr. Die vorgelagerte Infrastruktur weist sie ab, sodass eine bloße 413 ohne JSON-Body zurückkommt: ein Client, der jeden Fehler als JSON parst, wird daran scheitern, statt ihn zu melden. Diese Größe gehört in Teile aufgeteilt.

ParameterRolle
nameDateiname, .safetensors, Buchstaben, Ziffern, . _ -, maximal 80 Zeichen. Ein bereits vorhandener Name wird ersetzt.
kindimage (Standard) oder video. Benötigt entsprechend die Berechtigung images oder videos.
triggerDas Triggerwort, das im Prompt angegeben werden muss, maximal 60 Zeichen.
bash
curl -s -X POST "$B/loras/upload?name=my_character.safetensors&kind=image&trigger=ohwx"   -H "Authorization: Bearer $KEY" -H "Content-Type: application/octet-stream"   --data-binary @my_character.safetensors

Die Antwort lautet { "ok": true, "name": "my_character.safetensors", "kind": "image", "size": 314572800, "trigger": "ohwx", "architecture": "krea2", "storage": { ... } }.

Die Kompatibilität wird beim Hochladen geprüft. Bilder werden von Krea 2 gerendert, das eine eigene Architektur hat: nur eine Krea 2-LoRA wird angewendet, egal ob in tendre.AI oder anderswo für Krea 2 trainiert. Eine FLUX.1-LoRA wird abgelehnt, was nicht jeder auf Anhieb erwartet. Videos werden von LTX 2.5 gerendert, also eine LTX 2.5 oder 2.3-LoRA.

Die API liest den Datei-Header, bevor sie etwas speichert. Eine LoRA, die als SDXL, SD 1.5, SD3, FLUX.1, Wan oder HunyuanVideo erkannt wird, wird mit 415 incompatible_lora abgewiesen, das die gefundene architecture nennt, und eine Datei, die keine Safetensors-Datei ist, mit 415 invalid_safetensors. In beiden Fällen wird nichts gespeichert und kein Kontingent verbraucht.

Ein Fall kommt trotzdem durch: eine Architektur, die der Header nicht identifiziert, wird akzeptiert, mit architecture: "inconnue", und erst beim Rendern beurteilt. Das ist der einzige Fehler, der dich einen Render kostet, um ihn zu entdecken.

Eine große LoRA in Teilen senden

Drei Aufrufe, plus einen zum Abbrechen.

1. Sitzung öffnen. POST /loras/upload/start mit { "name", "kind", "size", "trigger" }, wobei size die gesamte Dateigröße in Bytes ist. Es prüft Name, Größe und Kontingent und antwortet dann:

json
{ "uploadId": "...", "part_size": 20971520, "max_part_size": 104857600, "parts_expected": 15 }

2. Jeden Teil senden. POST /loras/upload/part?uploadId=...&part=N, roher Body, Teile ab 1 nummeriert, je part_size Bytes außer beim letzten, niemals mehr als max_part_size. Jede Antwort enthält ein etag, und du brauchst alle davon für den nächsten Schritt, also speichere sie unterwegs.

Teil 1 ist besonders: er enthält den Datei-Header, hier wird also die Architektur beurteilt. Eine inkompatible LoRA wird dort mit 415 abgefangen und die Sitzung abgebrochen. Du erfährst es nach 20 MB statt nach 400.

3. Abschließen. POST /loras/upload/finish mit { "uploadId", "parts": [ { "part": 1, "etag": "..." }, ... ] }. Es setzt die Datei zusammen und registriert sie, mit einer Antwort genau wie beim einmaligen Upload.

Zum Abbrechen POST /loras/upload/abort mit { "uploadId" }. Eine Sitzung ohne finish wird nach sechs Stunden verworfen. In GET /loras erscheint nichts und nichts wird auf das Kontingent angerechnet, bis finish erfolgreich ist, sodass ein unterbrochener Upload keinen Speicherplatz kostet.

python
import os, requests
B, H = "https://api.tendre.ai/pro/v1", {"Authorization": "Bearer " + KEY}
path = name = "my_character.safetensors"
s = requests.post(f"{B}/loras/upload/start", headers=H,
                  json={"name": name, "kind": "image", "size": os.path.getsize(path), "trigger": "ohwx"}).json()
parts = []
with open(path, "rb") as f:
    n = 1
    while chunk := f.read(s["part_size"]):
        r = requests.post(f"{B}/loras/upload/part",
                          headers={**H, "Content-Type": "application/octet-stream"},
                          params={"uploadId": s["uploadId"], "part": n}, data=chunk)
        r.raise_for_status()
        parts.append({"part": n, "etag": r.json()["etag"]})
        n += 1
done = requests.post(f"{B}/loras/upload/finish", headers=H,
                     json={"uploadId": s["uploadId"], "parts": parts}).json()
print(done["name"], done["architecture"], done["storage"])

Ein fertiges PowerShell-Skript wird mit der App geliefert, unter scripts/api-pro-lora.ps1.

Eine LoRA löschen

DELETE /loras/{name}?kind=image|video entfernt die Datei und gibt das Kontingent frei. Die Antwort lautet { "ok": true, "name": ..., "storage": { ... } }, oder 404 unknown_lora, wenn der Name auf dem Account nicht existiert.

Speicherkontingent

Jede Lizenz erhält maximal 20 Dateien und 10 GB, Bilder und Videos zusammen, und die in der App trainierten Charaktere zählen dazu. GET /loras meldet den Stand unter storage:

json
{ "count": 3, "max_count": 20, "bytes": 943718400, "max_bytes": 10737418240 }

Sobald eines der Limits erreicht ist, antwortet ein Upload mit 413 lora_quota und zeigt, was noch verfügbar ist. Lösche eine Datei, um Platz zu schaffen.

Das Training eines Charakters ist über die API noch nicht verfügbar. Es geschieht in der App, und das Ergebnis erscheint in dieser Liste.

Aktivität

Die App führt das Protokoll jedes Renders, den deine Keys durchgeführt haben (Datum, Key, Typ, Kosten, Status), sowie den Verbrauch pro Key, unter Einstellungen > API > Aktivität.

Dort widerrufst du auch einen Key, der kompromittiert wurde, ohne die anderen zu berühren.

Windows · Mac · Cloud oder lokal

Privat generieren. Noch heute Abend.

Lade tendre.AI kostenlos herunter und generiere unbegrenzt, privat, auf deiner eigenen GPU.

OS Windows 10/11GPU NVIDIA 8GB+VRAM 12GB empfohlenDisk 20GB

Mac: Apple Silicon (M1 oder neuer), macOS 13 oder neuer. Intel-Macs werden nicht unterstützt.

Lokale Bildgenerierung auf dem Mac braucht einen M4 mit 24 GB Arbeitsspeicher oder einen M2 oder M3 Pro, Max oder Ultra mit 24 GB. Darunter läuft alles online mit Credits. Retusche und Video laufen auf dem Mac vorerst online.

Alles über tendre.AI für Mac

Keine NVIDIA-GPU? Starte zu 100% in der Cloud: täglich 5 kostenlose Bilder und 1 kostenloses Video. Eine NVIDIA-Karte (8GB+) schaltet unbegrenzte lokale Generierung frei.