API Pro: saldo, límites y personajes entrenados

Dos rutas de lectura, siempre permitidas sea cual sea el permiso de la clave, más el registro de actividad disponible en la app.

Saldo y límites

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_..." }
CampoSignificado
balanceCréditos restantes. null cuando el saldo es desconocido (entorno de prueba).
licenseIdLa licencia a la que pertenece esta clave.
keyEl identificador público de la clave, seguro para registrar. Nunca el secreto.
limits.concurrentRenders ejecutándose a la vez, 2 por defecto.
limits.perMinuteEnvíos por minuto, 60 por defecto.
limits.perDayLímite diario de créditos que has establecido en la clave. 0 significa sin límite.
runningRenders de esta clave que aún esperan ser recogidos.
buy_urlLa página de compra de créditos de tu licencia, con tarjeta o criptomoneda.

Esta es la llamada más económica de la API y la indicada para comprobar que una clave funciona.

Comprar créditos con tu tarjeta guardada

POST /credits/purchase

json
{ "pack": "m" }

pack es un id de pack (s, m, l, xl, xxl o xxxl), o "c25000" para una cantidad libre por encima del pack más grande. El pago se hace con la tarjeta guardada en la recarga automática de tu página de cuenta, solo si allí has autorizado a tu agente a comprar, dentro del límite mensual que has fijado (recargas automáticas incluidas). Un correo electrónico confirma cada compra. Una compra a la vez.

La respuesta es 200 { credits, eur, balance }. Cada rechazo incluye buy_url, el enlace de compra normal, para usarlo en su lugar: 402 confirmation_required (tu banco pide tu confirmación) 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 no sabemos si el cargo se ha realizado: no vuelvas a intentarlo enseguida, un cargo realizado se acredita.

Personajes entrenados

Son los personajes entrenados como LoRA, para imágenes y vídeos ordinarios. Los personajes de Multi-Ref Vídeo, siete vistas generadas a partir de una foto, son otra cosa: consulta Characters.

GET /loras

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

Pasa name como lora, tomándolo de la lista image para imágenes y de la lista video para vídeos, y pon su trigger en el prompt, de lo contrario el personaje no aparecerá. Un personaje que no pertenece a la cuenta devuelve 403 unknown_lora.

Sube tu propio LoRA

POST /loras/upload

Un archivo .safetensors que ya tengas, entrenado en otro lugar o alojado en tu propio servidor, se incorpora al espacio de la cuenta y queda disponible mediante lora, exactamente igual que un personaje entrenado en la app. Hay dos formas de hacerlo: de una vez hasta 90 MB, o en partes a partir de ese tamaño. Un LoRA suele pesar entre 200 y 500 MB, así que la segunda opción es el caso habitual. El límite máximo es de 800 MB en ambos casos.

De una vez: cuerpo en bruto (application/octet-stream, Content-Length requerido), parámetros en la URL.

A partir de 100 MB la solicitud nunca llega a la API. La infraestructura que está por delante la rechaza, por lo que lo que se recibe es un 413 simple sin cuerpo JSON: un cliente que intente analizar cada error como JSON fallará en lugar de informarlo. Ese tamaño corresponde a partes.

ParámetroFunción
nameNombre del archivo, .safetensors, letras, dígitos, . _ -, 80 caracteres como máximo. Un nombre ya existente se reemplaza.
kindimage (el valor por defecto) o video. Requiere el permiso images o videos según corresponda.
triggerLa palabra de activación que hay que incluir en el prompt, 60 caracteres como máximo.
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 respuesta es { "ok": true, "name": "my_character.safetensors", "kind": "image", "size": 314572800, "trigger": "ohwx", "architecture": "krea2", "storage": { ... } }.

La compatibilidad se comprueba al subir. Las imágenes se renderizan con Krea 2, que tiene su propia arquitectura: solo aplica un LoRA de Krea 2, tanto si fue entrenado en tendre.AI como para Krea 2 en otro sitio. Ten en cuenta que un LoRA de FLUX.1 es rechazado, lo que no es lo primero que uno esperaría. Los vídeos se renderizan con LTX 2.5, por lo que corresponde un LoRA de LTX 2.5 o 2.3.

La API lee la cabecera del archivo antes de almacenar nada. Un LoRA reconocido como SDXL, SD 1.5, SD3, FLUX.1, Wan o HunyuanVideo es rechazado con 415 incompatible_lora, que indica la architecture detectada, y un archivo que no sea safetensors recibe 415 invalid_safetensors. En ninguno de los dos casos se almacena nada ni se consume cuota.

Un caso todavía pasa: una arquitectura que la cabecera no identifica es aceptada, con architecture: "inconnue", y solo se juzga en el momento del render. Ese es el único error que te cuesta un render descubrir.

Envía un LoRA grande en partes

Tres llamadas, más una para cancelar.

1. Abre la sesión. POST /loras/upload/start con { "name", "kind", "size", "trigger" }, donde size es el archivo completo en bytes. Comprueba el nombre, el tamaño y la cuota, y responde:

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

2. Envía cada parte. POST /loras/upload/part?uploadId=...&part=N, cuerpo en bruto, partes numeradas desde 1, part_size bytes cada una excepto la última, nunca más de max_part_size. Cada respuesta incluye un etag, y los necesitas todos para el siguiente paso, así que guárdalos a medida que avances.

La parte 1 es especial: lleva la cabecera del archivo, por lo que ahí es donde se evalúa la arquitectura. Un LoRA incompatible se detecta allí con 415 y la sesión se cancela. Lo sabes tras 20 MB en lugar de tras 400.

3. Ciérrala. POST /loras/upload/finish con { "uploadId", "parts": [ { "part": 1, "etag": "..." }, ... ] }. Ensambla el archivo y lo registra, respondiendo exactamente igual que la subida de una vez.

Para cancelar, POST /loras/upload/abort con { "uploadId" }. Una sesión sin finish se descarta tras seis horas. Nada aparece en GET /loras y nada cuenta contra la cuota hasta que finish tiene éxito, así que una subida interrumpida no te cuesta nada de almacenamiento.

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

Un script de PowerShell listo para usar viene incluido con la app, en scripts/api-pro-lora.ps1.

Elimina un LoRA

DELETE /loras/{name}?kind=image|video elimina el archivo y libera la cuota. Responde con { "ok": true, "name": ..., "storage": { ... } }, o 404 unknown_lora cuando el nombre no existe en la cuenta.

Cuota de almacenamiento

Cada licencia dispone de 20 archivos y 10 GB como máximo, imágenes y vídeos juntos, y los personajes entrenados en la app cuentan hacia ese límite. GET /loras informa del estado en storage:

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

Si se supera cualquiera de los dos límites, una subida responde con 413 lora_quota junto con lo que queda. Elimina un archivo para liberar espacio.

Entrenar un personaje todavía no está expuesto por la API. Ocurre en la app, y el resultado aparece en esta lista.

Actividad

La app guarda el registro de cada render que han realizado tus claves (fecha, clave, tipo, coste, estado) y el consumo por clave, en Ajustes > API > Activity.

También es donde revocas una clave que haya quedado expuesta, sin tocar las demás.

Windows · Mac · Nube o local

Genera en privado. Esta noche.

Descarga tendre.AI gratis y genera sin límites, de forma privada, en tu propia GPU.

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

Mac: Apple silicon (M1 o posterior), macOS 13 o posterior. Los Mac con Intel no son compatibles.

La generación de imágenes local en Mac necesita un M4 con 24 GB de memoria, o un M2 o M3 Pro, Max o Ultra con 24 GB. Por debajo de eso, todo se ejecuta online con créditos. El retoque y el video se ejecutan online en Mac por ahora.

Todo sobre tendre.AI para Mac

¿No tienes GPU NVIDIA? Empieza 100% en la nube: 5 imágenes y 1 vídeo gratis cada día. Una tarjeta NVIDIA (8GB+) desbloquea la generación local ilimitada.