Pro API: saldo, grænser og trænede karakterer
To læseruter, altid tilladt uanset nøglens tilladelser, plus aktivitetsloggen i appen.
Saldo og grænser
GET /credits
{ "balance": 1830, "licenseId": "lic_...", "key": "k_1a2b3c4d",
"limits": { "concurrent": 2, "perMinute": 60, "perDay": 0 }, "running": 1,
"buy_url": "https://tendre.ai/credits?license=lic_..." }| Felt | Betydning |
|---|---|
balance | Tilbageværende kreditter. null når saldoen er ukendt (testmiljø). |
licenseId | Den licens denne nøgle tilhører. |
key | Nøglens offentlige identifikator, sikker at logge. Aldrig hemmeligheden. |
limits.concurrent | Renderinger der kører på én gang, 2 som standard. |
limits.perMinute | Indsendelser pr. minut, 60 som standard. |
limits.perDay | Daglig kreditgrænse du har sat på nøglen. 0 betyder ingen grænse. |
running | Renderinger fra denne nøgle der stadig venter på at blive hentet. |
buy_url | Siden til køb af credits til din licens, med kort eller krypto. |
Dette er det billigste kald i API'et og det rigtige at bruge til at tjekke om en nøgle virker.
Køb credits med dit gemte kort
POST /credits/purchase
{ "pack": "m" }pack er et pakke-id (s, m, l, xl, xxl eller xxxl), eller "c25000" for et valgfrit antal over den største pakke. Betalingen trækkes på kortet, der er gemt i den automatiske optankning på din kontoside, kun hvis du dér har tilladt din agent at købe, inden for den månedlige grænse, du har sat dér (automatiske optankninger medregnet). En e-mail bekræfter hvert køb. Ét køb ad gangen.
Svaret er 200 { credits, eur, balance }. Hvert afslag indeholder buy_url, det almindelige købslink, som du bruger i stedet: 402 confirmation_required (din bank beder om din bekræftelse) eller payment_declined; 409 agent_not_allowed, no_saved_card, monthly_cap_reached, topup_in_progress eller purchase_in_progress; 400 unknown_pack. Ved 503 payment_unavailable ved vi ikke, om trækket gik igennem: prøv ikke igen med det samme, et træk, der gik igennem, bliver krediteret.
Trænede karakterer
Dette er karakterer trænet som en LoRA, til billeder og almindelige videoer. Karaktererne fra Multi-Ref Video, syv visninger lavet fra ét foto, er noget andet: se Characters.
GET /loras
{ "image": [ { "name": "megan_krea2", "trigger": "megan", "base": "krea2", "size": 0 } ],
"video": [ { "name": "megan_ltx", "trigger": "megan", "size": 0 } ] }Angiv name som lora, og hent den fra image-listen til billeder og video-listen til
videoer, og put its trigger in the prompt, ellers vil karakteren ikke vise sig. En
karakter der ikke tilhører kontoen returnerer 403 unknown_lora.
Upload din egen LoRA
POST /loras/upload
En .safetensors-fil du allerede har, trænet andetsteds eller liggende på din egen server,
uploades til kontoens plads og kan bruges via lora, præcis som en karakter trænet i appen.
Der er to måder at gøre det på: én gang op til 90 MB, eller i dele derover. En LoRA
vejer normalt 200 til 500 MB, så den anden mulighed er det almindelige tilfælde. Loftet er
800 MB uanset hvad.
Én gang: en råbody (application/octet-stream, Content-Length påkrævet), parametre i URL'en.
Over 100 MB når anmodningen aldrig frem til API'et. Infrastrukturen foran afviser den, så
det der returneres er en ren 413 med ingen JSON-body: en klient der parser alle fejl som
JSON vil gå ned i stedet for at rapportere dem. Den størrelse hører hjemme i dele.
| Parameter | Rolle |
|---|---|
name | Filnavn, .safetensors, bogstaver, cifre, . _ -, højst 80 tegn. Et navn der allerede er taget erstattes. |
kind | image (standard) eller video. Kræver henholdsvis images- eller videos-tilladelsen. |
trigger | Trigger-ordet der skal sættes tilbage i prompten, højst 60 tegn. |
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.safetensorsSvaret er { "ok": true, "name": "my_character.safetensors", "kind": "image", "size": 314572800, "trigger": "ohwx", "architecture": "krea2", "storage": { ... } }.
Kompatibilitet tjekkes ved upload. Billeder renderes af Krea 2, som har sin egen arkitektur: kun en Krea 2-LoRA virker, uanset om den er trænet i tendre.AI eller til Krea 2 andetsteds. Bemærk at en FLUX.1-LoRA afvises, hvilket ikke er alles første gæt. Videoer renderes af LTX 2.5, så det skal være en LTX 2.5 eller 2.3-LoRA.
API'et læser filens header inden noget gemmes. En LoRA der genkendes som SDXL, SD 1.5, SD3,
FLUX.1, Wan eller HunyuanVideo afvises med 415 incompatible_lora, som angiver den
architecture der blev fundet, og en fil der ikke er en safetensors med 415 invalid_safetensors.
Intet gemmes og ingen kvote bruges i nogen af tilfældene.
Ét tilfælde slipper stadig igennem: en arkitektur som headeren ikke identificerer accepteres,
med architecture: "inconnue", og bedømmes først ved renderingstidspunktet. Det er den ene fejl
der koster dig en rendering at opdage.
Send en stor LoRA i dele
Tre kald, plus ét til at opgive.
1. Åbn sessionen. POST /loras/upload/start med { "name", "kind", "size", "trigger" },
hvor size er hele filen i bytes. Det tjekker navn, størrelse og kvote, og svarer:
{ "uploadId": "...", "part_size": 20971520, "max_part_size": 104857600, "parts_expected": 15 }2. Send hver del. POST /loras/upload/part?uploadId=...&part=N, råbody, dele nummereret
fra 1, part_size bytes hver undtagen den sidste, aldrig mere end max_part_size. Hvert svar
indeholder et etag, og du skal bruge dem alle til næste trin, så gem dem undervejs.
Del 1 er særlig: den indeholder filens header, så det er her arkitekturen bedømmes. En
inkompatibel LoRA fanges der med 415 og sessionen annulleres. Du finder ud af det efter
20 MB frem for efter 400.
3. Luk den. POST /loras/upload/finish med { "uploadId", "parts": [ { "part": 1, "etag": "..." }, ... ] }.
Det samler filen og registrerer den, og svarer præcis som ved enkeltstående upload.
For at opgive, POST /loras/upload/abort med { "uploadId" }. En session uden finish slettes
efter seks timer. Intet vises i GET /loras og intet tæller mod kvoten før finish lykkes,
så en afbrudt upload koster dig ingen lagerplads.
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"])Et færdigt PowerShell-script følger med appen, under scripts/api-pro-lora.ps1.
Slet en LoRA
DELETE /loras/{name}?kind=image|video fjerner filen og frigiver kvoten. Det svarer med
{ "ok": true, "name": ..., "storage": { ... } }, eller 404 unknown_lora når navnet ikke
findes på kontoen.
Lagerkvote
Hver licens får højst 20 filer og 10 GB, billeder og videoer tilsammen, og karakterer
trænet i appen tæller med. GET /loras rapporterer tilstanden i storage:
{ "count": 3, "max_count": 20, "bytes": 943718400, "max_bytes": 10737418240 }Overskrides en af grænserne svarer et upload med 413 lora_quota samt hvad der er tilbage.
Slet en fil for at frigøre plads.
Træning af en karakter er stadig ikke tilgængeligt via API'et. Det sker i appen, og resultatet vises i denne liste.
Aktivitet
Appen gemmer loggen over alle renderinger dine nøgler har foretaget (dato, nøgle, type, omkostning, status) og forbruget pr. nøgle, under Settings > API > Activity.
Det er også her du tilbagekalder en nøgle der har lækket, uden at røre de andre.