API Pro: saldo, limiti e personaggi addestrati

Due route di sola lettura, sempre consentite qualunque sia il permesso della chiave, più il registro attività conservato nell'app.

Saldo e limiti

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_..." }
CampoSignificato
balanceCrediti rimanenti. null quando il saldo è sconosciuto (ambiente di test).
licenseIdLa licenza a cui appartiene questa chiave.
keyL'identificatore pubblico della chiave, sicuro da registrare nei log. Mai il segreto.
limits.concurrentRender in esecuzione contemporaneamente, 2 di default.
limits.perMinuteRichieste al minuto, 60 di default.
limits.perDayLimite giornaliero di crediti impostato sulla chiave. 0 significa nessun limite.
runningRender di questa chiave ancora in attesa di essere recuperati.
buy_urlLa pagina di acquisto dei crediti della tua licenza, con carta o crypto.

È la chiamata meno costosa dell'API e quella giusta per verificare che una chiave funzioni.

Acquistare crediti con la carta salvata

POST /credits/purchase

json
{ "pack": "m" }

pack è un id di pacchetto (s, m, l, xl, xxl o xxxl), oppure "c25000" per una quantità libera oltre il pacchetto più grande. Il pagamento avviene sulla carta salvata nella ricarica automatica della tua pagina account, solo se lì hai autorizzato il tuo agente ad acquistare, entro il limite mensile che hai fissato (ricariche automatiche comprese). Un'e-mail conferma ogni acquisto. Un acquisto alla volta.

La risposta è 200 { credits, eur, balance }. Ogni rifiuto contiene buy_url, il link di acquisto normale, da usare al suo posto: 402 confirmation_required (la tua banca chiede la tua conferma) o payment_declined; 409 agent_not_allowed, no_saved_card, monthly_cap_reached, topup_in_progress o purchase_in_progress; 400 unknown_pack. Con 503 payment_unavailable non sappiamo se l'addebito è avvenuto: non riprovare subito, un addebito avvenuto viene accreditato.

Personaggi addestrati

Questi sono i personaggi addestrati come LoRA, per immagini e video ordinari. I personaggi di Multi-Ref Video, sette viste ricavate da una foto, sono un'altra cosa: vedi Characters.

GET /loras

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

Passa name come lora, prendendolo dalla lista image per le immagini e dalla lista video per i video, e inserisci il suo trigger nel prompt, altrimenti il personaggio non apparirà. Un personaggio che non appartiene all'account risponde 403 unknown_lora.

Carica la tua LoRA

POST /loras/upload

Un file .safetensors che hai già, addestrato altrove o che si trova sul tuo server, viene inserito nello spazio dell'account e diventa utilizzabile tramite lora, esattamente come un personaggio addestrato nell'app. Ci sono due modalità: in un colpo solo fino a 90 MB, oppure a parti oltre tale soglia. Una LoRA di solito pesa dai 200 ai 500 MB, quindi la seconda è il caso ordinario. Il limite massimo è 800 MB in entrambi i casi.

In un colpo solo: un body grezzo (application/octet-stream, Content-Length obbligatorio), i parametri nell'URL.

Oltre i 100 MB la richiesta non raggiunge mai l'API. L'infrastruttura a monte la blocca, quindi ciò che si riceve è un semplice 413 senza body JSON: un client che analizza ogni errore come JSON si bloccherà invece di segnalarlo. Quella dimensione va inviata a parti.

ParametroRuolo
nameNome del file, .safetensors, lettere, cifre, . _ -, massimo 80 caratteri. Un nome già esistente viene sostituito.
kindimage (il default) o video. Richiede rispettivamente il permesso images o videos.
triggerLa parola trigger da inserire nel prompt, massimo 60 caratteri.
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

La risposta è { "ok": true, "name": "my_character.safetensors", "kind": "image", "size": 314572800, "trigger": "ohwx", "architecture": "krea2", "storage": { ... } }.

La compatibilità viene verificata al momento del caricamento. Le immagini sono renderizzate da Krea 2, che ha un'architettura propria: si applica solo una LoRA Krea 2, sia che sia stata addestrata in tendre.AI sia per Krea 2 altrove. Tieni presente che una LoRA FLUX.1 viene rifiutata, il che non è la prima cosa che si pensa. I video sono renderizzati da LTX 2.5, quindi serve una LoRA LTX 2.5 o 2.3.

L'API legge l'header del file prima di archiviare qualsiasi cosa. Una LoRA riconosciuta come SDXL, SD 1.5, SD3, FLUX.1, Wan o HunyuanVideo viene respinta con 415 incompatible_lora, che indica l'architecture rilevata, e un file che non è un safetensors con 415 invalid_safetensors. Nulla viene archiviato e nessuna quota viene consumata in nessuno dei due casi.

Un caso riesce comunque a passare: un'architettura che l'header non identifica viene accettata, con architecture: "inconnue", e viene valutata solo al momento del render. Questo è l'unico errore che ti costa un render per scoprirlo.

Invia una LoRA grande a parti

Tre chiamate, più una per annullare.

1. Apri la sessione. POST /loras/upload/start con { "name", "kind", "size", "trigger" }, dove size è l'intero file in byte. Verifica il nome, la dimensione e la quota, poi risponde:

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

2. Invia ogni parte. POST /loras/upload/part?uploadId=...&part=N, body grezzo, parti numerate a partire da 1, part_size byte ciascuna tranne l'ultima, mai più di max_part_size. Ogni risposta contiene un etag, e ne hai bisogno di tutti per il passaggio successivo, quindi conservali man mano.

La parte 1 è speciale: contiene l'header del file, quindi è lì che viene valutata l'architettura. Una LoRA incompatibile viene intercettata lì con 415 e la sessione viene annullata. Lo scopri dopo 20 MB invece che dopo 400.

3. Chiudi la sessione. POST /loras/upload/finish con { "uploadId", "parts": [ { "part": 1, "etag": "..." }, ... ] }. Assembla il file e lo registra, rispondendo esattamente come l'upload in un colpo solo.

Per annullare, POST /loras/upload/abort con { "uploadId" }. Una sessione lasciata senza finish viene eliminata dopo sei ore. Nulla appare in GET /loras e nulla viene contato contro la quota finché finish non riesce, quindi un upload interrotto non ti costa storage.

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"])

Con l'app viene fornito uno script PowerShell già pronto, disponibile in scripts/api-pro-lora.ps1.

Elimina una LoRA

DELETE /loras/{name}?kind=image|video rimuove il file e libera la quota. Risponde con { "ok": true, "name": ..., "storage": { ... } }, oppure 404 unknown_lora quando il nome non esiste sull'account.

Quota di storage

Ogni licenza dispone di un massimo di 20 file e 10 GB, immagini e video insieme, e i personaggi addestrati nell'app vi contribuiscono. GET /loras riporta lo stato in storage:

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

Superato uno dei due limiti, un upload risponde 413 lora_quota insieme a quanto rimane. Elimina un file per fare spazio.

L'addestramento di un personaggio non è ancora esposto dall'API. Avviene nell'app, e il risultato appare in questo elenco.

Attività

L'app conserva il registro di ogni render effettuato dalle tue chiavi (data, chiave, tipo, costo, stato) e il consumo per chiave, in Impostazioni > API > Attività.

È anche lì che puoi revocare una chiave che è stata compromessa, senza toccare le altre.

Windows · Mac · Cloud o locale

Genera in privato. Stasera.

Scarica tendre.AI gratis e genera senza limiti, in privato, sulla tua GPU.

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

Mac: Apple silicon (M1 o successivo), macOS 13 o successivo. I Mac Intel non sono supportati.

La generazione di immagini in locale su Mac richiede un M4 con 24 GB di memoria, oppure un M2 o M3 Pro, Max o Ultra con 24 GB. Al di sotto, tutto funziona online con i crediti. Per ora, ritocco e video su Mac funzionano online.

Tutto su tendre.AI per Mac

Non hai una GPU NVIDIA? Parti al 100% nel cloud: 5 immagini gratuite e 1 video gratuito ogni giorno. Una scheda NVIDIA (8GB+) sblocca la generazione locale illimitata.