PhotoGPT Developers

Trigger training after a model has enough input images.

Training

Training turns a model with uploaded modelInput images into a trained model that can be used by POST /images/generation.

Training time

Model training usually takes 20 to 25 minutes. After you trigger training, poll the model status with a long interval such as 5 minutes. Do not poll every second; it will not make training complete faster and can cause unnecessary API load.

Prerequisites

Before triggering training:

  • Create the model with POST /models.
  • Upload 12 to 20 modelInput images for that model.
  • Confirm the model and images belong to the authenticated API key.

The API returns 400 when image count or request data is invalid, and 429 when too many trainings are already running.

Trigger model training

Use GET /models/{modelID}/train to start training. The request only starts the training process; the model will move through backend training states before it becomes ready.

const modelId = '<MODEL_ID>'

const response = await fetch(`${BASE_URL}/models/${modelId}/train`, {
  headers,
})

if (!response.ok) {
  throw new Error(await response.text())
}

const trainingResult = await response.json()
model_id = "<MODEL_ID>"

response = requests.get(f"{BASE_URL}/models/{model_id}/train", headers=headers)
response.raise_for_status()

training_result = response.json()

Track readiness

The OpenAPI schema documents the training trigger response as a success string. It does not document a training jobId, so treat the model status as the source of truth.

Use a 5-minute polling interval for normal integrations. A client-side UI can show the model as training and refresh periodically, or let the user leave and come back later.

const TRAINING_POLL_INTERVAL_MS = 5 * 60 * 1000
const TRAINING_TIMEOUT_MS = 35 * 60 * 1000
const startedAt = Date.now()

while (true) {
  const response = await fetch(`${BASE_URL}/models/${modelId}`, {
    headers,
  })

  if (!response.ok) {
    throw new Error(await response.text())
  }

  const body = await response.json()
  const model = body.result
  const status = String(model.status ?? '').toLowerCase()

  if (status === 'ready') {
    break
  }

  if (status === 'deleted') {
    throw new Error(`Model cannot be used for generation: ${status}`)
  }

  if (Date.now() - startedAt > TRAINING_TIMEOUT_MS) {
    throw new Error('Training is still running. Check the model status again later.')
  }

  await new Promise((resolve) => setTimeout(resolve, TRAINING_POLL_INTERVAL_MS))
}
import time

TRAINING_POLL_INTERVAL_SECONDS = 5 * 60
TRAINING_TIMEOUT_SECONDS = 35 * 60
started_at = time.monotonic()

while True:
    response = requests.get(f"{BASE_URL}/models/{model_id}", headers=headers)
    response.raise_for_status()

    model = response.json()["result"]
    status = str(model.get("status", "")).lower()

    if status == "ready":
        break

    if status in {"deleted"}:
        raise RuntimeError(f"Model cannot be used for generation: {status}")

    if time.monotonic() - started_at > TRAINING_TIMEOUT_SECONDS:
        raise RuntimeError("Training is still running. Check the model status again later.")

    time.sleep(TRAINING_POLL_INTERVAL_SECONDS)

When the model is ready, use its ID with POST /images/generation.

API reference

On this page