Nodaro Docs
DocumentationNode ReferenceModelsAI Agents (MCP)DevelopersSelf-hostingResearch
REST API

Character training

Train a high-fidelity model on a character over REST, poll the training, remove the model, and learn when Generate Image uses the trained model.

Available on Nodaro Cloud

Character training creates a dedicated model of one character from its images, for the closest likeness in Generate Image. You start a training with one call, poll it until it finishes, and remove the model when you no longer need it. After training, Generate Image uses the trained model automatically whenever a prompt mentions that character.

Character training runs on Nodaro Cloud only; on self-hosted installs the routes do not exist and answer 404. On a self-hosted install, keep a character consistent with its approved portrait and reference images, as described in Characters. The routes take a bearer token and act only on your own characters. See Authentication.

Endpoints

MethodPathWhat it does
POST/v1/characters/:id/trainStart a training. Reserves 1,500 credits.
GET/v1/characters/:id/trainingGet the training status.
DELETE/v1/characters/:id/loraCancel a training in progress, or remove the trained model.

Before you train

The character needs at least 4 different images. Nodaro collects them from the character, in this order, removes duplicates, and trains on up to 20:

  1. The approved portrait.
  2. The reference photos.
  3. The expressions, the poses, the head angles and the body angles.
  4. The lighting variants.

Character sheets do not count, because their views repeat the angles. When a character has fewer than 4 images, generate a few angles and expressions first with POST /v1/generate-character-asset; see Characters.

Start a training

POST /v1/characters/:id/train reserves 1,500 credits and starts the training. It answers 202 with the training's job id, its id and the character's trigger word. You never need to type the trigger word: Nodaro adds it to prompts for you.

curl -X POST https://app.nodaro.ai/v1/characters/3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94/train \
  -H "Authorization: Bearer $NODARO_API_KEY"
import { createClient, StaticTokenAuth } from '@nodaro/sdk'

const client = createClient({
  baseUrl: 'https://app.nodaro.ai',
  auth: new StaticTokenAuth(process.env.NODARO_API_KEY!),
})

// The SDK has no training methods yet; its generic request method calls the route.
const training = await client.request('POST', `/v1/characters/${characterId}/train`)
{
  "jobId": "7a9c1e3b-5d2f-4b8a-9c6e-1f3d5b7a9c2e",
  "trainingId": "q4m8x2k6p1",
  "triggerWord": "TOK_kira_a1b2c3"
}

A double click is safe: while a training is queued or running, another start answers 409 already_training_or_not_found and reserves nothing. Each token may start 3 trainings per minute.

Follow the training

GET /v1/characters/:id/training returns the training's state. A training takes about 15 minutes. Poll every few seconds; the editor polls every 8 seconds.

curl https://app.nodaro.ai/v1/characters/3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94/training \
  -H "Authorization: Bearer $NODARO_API_KEY"
type Training = { status: string; error: string | null; triggerWord: string | null }

const path = `/v1/characters/${characterId}/training`
let state = await client.request<Training>('GET', path)
while (state.status === 'queued' || state.status === 'training') {
  await new Promise((resolve) => setTimeout(resolve, 8000))
  state = await client.request<Training>('GET', path)
}
{
  "status": "succeeded",
  "trainingId": "q4m8x2k6p1",
  "error": null,
  "trainedAt": "2026-09-20T11:42:08Z",
  "version": "b81f4c0e9d27",
  "triggerWord": "TOK_kira_a1b2c3",
  "imageCount": 12
}
FieldWhat it holds
statusuntrained, queued, training, succeeded, failed or cancelled.
trainingIdThe current or last training, or null.
errorWhy the training failed, or null.
trainedAtWhen the model finished training, or null.
versionThe trained model's version, or null.
triggerWordThe word that calls up the character in the trained model, or null.
imageCountHow many images the model was trained on, or null.

Generate images with the trained model

Once the status is succeeded, run Generate Image with a prompt that mentions exactly one trained character with @, and with that character wired into the node. Nodaro then uses the trained model instead of the selected model and the reference images:

  • Automatic. The trigger word is put at the start of the prompt for you, and your @ mentions are removed from the text.
  • 20 credits per image. The trained model's price replaces the selected model's price.
  • One trained character at a time. When the prompt mentions two or more trained characters, Generate Image falls back to the selected model with reference images.
  • Generate Image only. Other nodes, such as Modify Image and the video nodes, keep using the character's reference images.

See Run a single node for the Generate Image request, and Character training for the same feature in the editor.

Re-train or remove the model

  • Re-train. Start a training again at any time after one has succeeded, failed or been cancelled. It costs 1,500 credits every time and replaces the previous model.
  • Remove. DELETE /v1/characters/:id/lora cancels a training in progress and refunds its credits, deletes the trained model, and clears the character's training fields. It returns { ok: true }. Generations go back to reference images.
  • Archive the character. Archiving the character also cancels a training in progress, refunds its credits and deletes the trained model.
curl -X DELETE https://app.nodaro.ai/v1/characters/3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94/lora \
  -H "Authorization: Bearer $NODARO_API_KEY"

Credits

ActionCredits
A training1,500, refunded when the training fails or is cancelled.
A re-training1,500 every time.
An image from the trained model20 per image, instead of the selected model's price.

See Credits for balances and transactions.

Errors

StatusCodeMeaning
400insufficient_training_imagesThe character has fewer than 4 different images. Add angles or expressions and try again.
401unauthorizedThe token is missing, invalid or revoked.
402insufficient_creditsThe account cannot cover the 1,500 credits.
404not_foundNo such character belongs to you, or the instance is not Nodaro Cloud.
409already_training_or_not_foundA training is already queued or running for this character, or the character is not yours.
429—More than 3 training starts in a minute from this token.
502training_dispatch_failedThe training service refused the request. The credits are refunded.
503public_url_not_configured, webhook_not_configuredTraining is not configured on this instance.

Frequently asked questions

Last updated on

On this page