Skip to content

API reference · v1

Trainings

Training through the XEYE API: estimate the price, retrain a list, poll its status until completed and choose the embedding model.

How a training works

Training computes the embeddings of every element in the list (and, if the list allows it, generates AI descriptions for the ones without) and puts that model into use for the search. You launch it: edits only leave one pending training per list. It consumes credit; the estimate tells you how much before launching.

Statuses

StatusMeaning
pendingThere are untrained changes; waiting for you to launch.
queuedLaunched, waiting in the queue (queue_position = 1 is next).
initializedHanded to the worker; starting up.
optimizingGenerating AI descriptions (if applicable).
trainingComputing embeddings.
completedFinished: the model is in use (in_use) and the search already serves it.
failedFailed or stalled; error says why. Credit is refunded and the list stays pending.
If the balance is not enough, launching answers 402 INSUFFICIENT_CREDIT with details.required and details.balance, and the pending training is kept. Top up credit from the console.

Endpoints

Estimate the price

GEThttps://api.xeye.es/v1/lists/{listId}/trainings/estimateScope: trainings:read

Price of launching now: the fixed part plus the enrichment of the elements without a cached description; sufficient tells whether the balance covers it.

Parameters
FieldInTypeRequiredDescription
listIdpathintegeryesList id.
regenerate_descriptionsquerybooleannoRegenerate the AI descriptions of every element even if cached (more expensive). Default false.
no_descriptionsquerybooleannoTrain without AI descriptions; wins over regenerate_descriptions and is the cheapest. Default false.

Request

bash
curl -X GET https://api.xeye.es/v1/lists/42/trainings/estimate \
  -H "X-API-Key: $XEYE_API_KEY"

Response

200 OK · application/json
{
  "descriptions_to_generate": 250,
  "fixed": 0.3,
  "enrichment": 1.325,
  "total": 1.625,
  "balance": 5.0,
  "sufficient": true
}

Retrain the list

POSThttps://api.xeye.es/v1/lists/{listId}/trainingsScope: trainings:write

Queues the training of the list (reuses the pending one or creates it) and charges its price. The response carries the run as it stands; poll GET /trainings/{id} until completed or failed.

Parameters
FieldInTypeRequiredDescription
listIdpathintegeryesList id.
embedding_modelbodystringnoOne of GET /trainings/embedding-models; absent = the default.
regenerate_descriptionsbodybooleannoRegenerate the AI descriptions of every element even if cached (more expensive). Default false.
no_descriptionsbodybooleannoTrain without AI descriptions; wins over regenerate_descriptions and is the cheapest. Default false.

Request

bash
curl -X POST https://api.xeye.es/v1/lists/42/trainings \
  -H "X-API-Key: $XEYE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "no_descriptions": false
  }'

Response

200 OK · application/json
{
  "id": 310,
  "list_id": 42,
  "status": "queued",
  "embedding_model": "intfloat/multilingual-e5-small",
  "element_count": 250,
  "described_count": null,
  "in_use": false,
  "has_embeddings": false,
  "usable": false,
  "queue_position": 1,
  "error": null,
  "cost": { "fixed": 0.3, "enrichment": 1.325, "total": 1.625 },
  "time": null,
  "last_heartbeat_at": null,
  "created_at": "2026-10-14T09:20:00Z",
  "updated_at": "2026-10-14T09:20:00Z"
}

Training status

GEThttps://api.xeye.es/v1/trainings/{id}Scope: trainings:read

Status of a training. This is the polling endpoint: every few seconds is enough.

Parameters
FieldInTypeRequiredDescription
idpathintegeryesTraining id.

Request

bash
curl -X GET https://api.xeye.es/v1/trainings/310 \
  -H "X-API-Key: $XEYE_API_KEY"

Response

200 OK · application/json
{
  "id": 310,
  "list_id": 42,
  "status": "completed",
  "embedding_model": "intfloat/multilingual-e5-small",
  "element_count": 250,
  "described_count": 250,
  "in_use": true,
  "has_embeddings": true,
  "usable": true,
  "queue_position": null,
  "error": null,
  "cost": { "fixed": 0.3, "enrichment": 1.325, "total": 1.625 },
  "time": { "optimizing_seconds": 12, "training_seconds": 95, "total_seconds": 107 },
  "last_heartbeat_at": null,
  "created_at": "2026-10-14T09:20:00Z",
  "updated_at": "2026-10-14T09:20:00Z"
}

Training history

GEThttps://api.xeye.es/v1/lists/{listId}/trainingsScope: trainings:read

History of the list, newest first.

Parameters
FieldInTypeRequiredDescription
listIdpathintegeryesList id.
offsetqueryintegernoFirst item of the page, from 0.
limitqueryintegernoPage size, 1 to 200 (default 50).

Request

bash
curl -X GET https://api.xeye.es/v1/lists/42/trainings \
  -H "X-API-Key: $XEYE_API_KEY"

Response

200 OK · application/json
{
  "items": [ {
      "id": 310,
      "list_id": 42,
      "status": "queued",
      "embedding_model": "intfloat/multilingual-e5-small",
      "element_count": 250,
      "described_count": null,
      "in_use": false,
      "has_embeddings": false,
      "usable": false,
      "queue_position": 1,
      "error": null,
      "cost": { "fixed": 0.3, "enrichment": 1.325, "total": 1.625 },
      "time": null,
      "last_heartbeat_at": null,
      "created_at": "2026-10-14T09:20:00Z",
      "updated_at": "2026-10-14T09:20:00Z"
    } ],
  "total": 1,
  "offset": 0,
  "limit": 50
}

Launch a pending training

POSThttps://api.xeye.es/v1/trainings/{id}/launchScope: trainings:write

Launches a specific training in pending status (equivalent to retraining the list once you know its id).

Parameters
FieldInTypeRequiredDescription
idpathintegeryesTraining id.
embedding_modelbodystringnoOne of GET /trainings/embedding-models; absent = the default.
regenerate_descriptionsbodybooleannoRegenerate the AI descriptions of every element even if cached (more expensive). Default false.
no_descriptionsbodybooleannoTrain without AI descriptions; wins over regenerate_descriptions and is the cheapest. Default false.

Request

bash
curl -X POST https://api.xeye.es/v1/trainings/310/launch \
  -H "X-API-Key: $XEYE_API_KEY"

Response

200 OK · application/json
{
  "id": 310,
  "list_id": 42,
  "status": "queued",
  "embedding_model": "intfloat/multilingual-e5-small",
  "element_count": 250,
  "described_count": null,
  "in_use": false,
  "has_embeddings": false,
  "usable": false,
  "queue_position": 1,
  "error": null,
  "cost": { "fixed": 0.3, "enrichment": 1.325, "total": 1.625 },
  "time": null,
  "last_heartbeat_at": null,
  "created_at": "2026-10-14T09:20:00Z",
  "updated_at": "2026-10-14T09:20:00Z"
}

Embedding models

GEThttps://api.xeye.es/v1/trainings/embedding-modelsScope: trainings:read

Embedding models accepted in embedding_model. The first one is used when you send none.

Request

bash
curl -X GET https://api.xeye.es/v1/trainings/embedding-models \
  -H "X-API-Key: $XEYE_API_KEY"

Response

200 OK · application/json
{
  "models": ["intfloat/multilingual-e5-small", "intfloat/multilingual-e5-base"],
  "default_model": "intfloat/multilingual-e5-small"
}
A list admits only one training queued or running at a time: a second launch answers 409 CONFLICT until the first finishes. The list must have elements (400 if empty).
Poll every 5–10 seconds: a training takes from under a minute to several, depending on the list size and the descriptions to generate. Do not repeat the POST if you get no response: check the history first.