Pro API: saldo, grenser og trente karakterer
To lese-endepunkter, alltid tillatt uavhengig av nøkkelens tillatelser, pluss aktivitetsloggen i appen.
Saldo og grenser
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 | Gjenværende kreditter. null når saldoen er ukjent (testmiljø). |
licenseId | Lisensen denne nøkkelen tilhører. |
key | Nøkkelens offentlige identifikator, trygg å logge. Aldri selve hemmeligheten. |
limits.concurrent | Renderinger som kjører samtidig, 2 som standard. |
limits.perMinute | Innsendinger per minutt, 60 som standard. |
limits.perDay | Daglig kredittgrense du setter på nøkkelen. 0 betyr ingen grense. |
running | Renderinger fra denne nøkkelen som fremdeles venter på å bli hentet. |
buy_url | Siden for kjøp av kreditter til lisensen din, med kort eller krypto. |
Dette er det billigste kallet i API-et og det rette å bruke for å sjekke at en nøkkel fungerer.
Kjøpe kreditter med det lagrede kortet ditt
POST /credits/purchase
{ "pack": "m" }pack er en pakke-id (s, m, l, xl, xxl eller xxxl), eller "c25000" for et valgfritt antall over den største pakken. Betalingen trekkes fra kortet som er lagret i den automatiske påfyllingen på kontosiden din, bare hvis du der har tillatt agenten din å kjøpe, innenfor månedsgrensen du har satt der (automatiske påfyllinger medregnet). En e-post bekrefter hvert kjøp. Ett kjøp om gangen.
Svaret er 200 { credits, eur, balance }. Hvert avslag inneholder buy_url, den vanlige kjøpslenken, som du bruker i stedet: 402 confirmation_required (banken din ber om bekreftelse) 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 vet vi ikke om trekket gikk gjennom: ikke prøv igjen med en gang, et trekk som gikk gjennom blir kreditert.
Trente karakterer
Dette er karakterene trent som en LoRA, for bilder og vanlige videoer. Karakterene i Multi-Ref Video, sju visninger laget fra ett foto, er noe annet: se Characters.
GET /loras
{ "image": [ { "name": "megan_krea2", "trigger": "megan", "base": "krea2", "size": 0 } ],
"video": [ { "name": "megan_ltx", "trigger": "megan", "size": 0 } ] }Send name som lora, hent det fra image-listen for bilder og video-listen for
videoer, og legg inn trigger-ordet i prompten, ellers vil ikke karakteren vises. En
karakter som ikke tilhører kontoen svarer med 403 unknown_lora.
Last opp din egen LoRA
POST /loras/upload
En .safetensors-fil du allerede har, trent et annet sted eller lagret på din egen server, lastes
opp til kontoens plass og blir tilgjengelig via lora, akkurat som en karakter trent i appen.
Det er to måter å gjøre det på: ett skudd opp til 90 MB, eller i deler utover det. En LoRA
veier vanligvis 200 til 500 MB, så den andre metoden er normaltilfellet. Taket er 800 MB uansett.
Ett skudd: en rå body (application/octet-stream, Content-Length er påkrevd), parametere i
URL-en.
Over 100 MB når forespørselen aldri frem til API-et. Infrastrukturen foran avviser den, så
det som kommer tilbake er en ren 413 uten JSON-body: en klient som tolker alle feil som JSON
vil krasje på det i stedet for å rapportere feilen. Den størrelsen hører hjemme i deler.
| Parameter | Rolle |
|---|---|
name | Filnavn, .safetensors, bokstaver, siffer, . _ -, maks 80 tegn. Et navn som allerede er tatt erstattes. |
kind | image (standard) eller video. Krever henholdsvis images- eller videos-tillatelsen. |
trigger | Trigger-ordet som skal legges inn i prompten, maks 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 sjekkes ved opplasting. Bilder renderes av Krea 2, som har sin egen arkitektur: bare en Krea 2 LoRA fungerer, enten den er trent i tendre.AI eller for Krea 2 et annet sted. Merk at en FLUX.1 LoRA avvises, noe som ikke er alles første tanke. Videoer renderes av LTX 2.5, så en LTX 2.5 eller 2.3 LoRA gjelder der.
API-et leser filhodet før noe lagres. En LoRA som gjenkjennes som SDXL, SD 1.5, SD3,
FLUX.1, Wan eller HunyuanVideo avvises med 415 incompatible_lora, som oppgir
architecture den fant, og en fil som ikke er en safetensors med 415 invalid_safetensors.
Ingenting lagres og ingen kvote brukes i noen av tilfellene.
Ett tilfelle slipper fortsatt gjennom: en arkitektur som hodet ikke identifiserer aksepteres, med
architecture: "inconnue", og vurderes først ved rendertidspunktet. Det er den ene feilen som koster
deg en rendering å oppdage.
Send en stor LoRA i deler
Tre kall, pluss ett for å avbryte.
1. Åpne sesjonen. POST /loras/upload/start med { "name", "kind", "size", "trigger" },
der size er hele filen i byte. Den sjekker 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, deler nummerert
fra 1, part_size byte hver unntatt den siste, aldri mer enn max_part_size. Hvert svar
inneholder en etag, og du trenger alle for neste steg, så ta vare på dem underveis.
Del 1 er spesiell: den inneholder filhodet, så det er der arkitekturen vurderes. En
inkompatibel LoRA fanges der med 415 og sesjonen avbrytes. Du finner ut etter
20 MB i stedet for etter 400.
3. Avslutt den. POST /loras/upload/finish med { "uploadId", "parts": [ { "part": 1, "etag": "..." }, ... ] }.
Den setter filen sammen og registrerer den, og svarer akkurat som ett-skudd-opplastingen.
For å avbryte: POST /loras/upload/abort med { "uploadId" }. En sesjon uten finish slettes
etter seks timer. Ingenting vises i GET /loras og ingenting teller mot kvoten
før finish lykkes, så en avbrutt opplasting koster deg ingen lagring.
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 ferdig PowerShell-skript følger med appen, under scripts/api-pro-lora.ps1.
Slett en LoRA
DELETE /loras/{name}?kind=image|video fjerner filen og frigjør kvoten. Den svarer med
{ "ok": true, "name": ..., "storage": { ... } }, eller 404 unknown_lora når navnet ikke
finnes på kontoen.
Lagringskvote
Hver lisens får maks 20 filer og 10 GB, bilder og videoer samlet, og karakterene
trent i appen teller med. GET /loras rapporterer tilstanden i storage:
{ "count": 3, "max_count": 20, "bytes": 943718400, "max_bytes": 10737418240 }Over en av grensene svarer en opplasting med 413 lora_quota sammen med hva som er igjen. Slett en fil for å frigjøre plass.
Trening av en karakter er foreløpig ikke tilgjengelig via API-et. Det skjer i appen, og resultatet dukker opp i denne listen.
Aktivitet
Appen lagrer loggen over alle renderinger nøklene dine har gjort (dato, nøkkel, type, kostnad, status) og forbruket per nøkkel, under Settings > API > Activity.
Det er også her du tilbakekaller en nøkkel som har lekket, uten å røre de andre.