Hosted model aliases
A hosted model is a stable project-local alias for a training job that produced an artifact — one that succeeded, or one you stopped after it had trained. Aliases are routing identities over a shared serving pool; creating one does not allocate a dedicated GPU.
Model lifecycle endpoints
GET /api/projects/{owner_slug}/{project_slug}/models
POST /api/projects/{owner_slug}/{project_slug}/models
PUT /api/projects/{owner_slug}/{project_slug}/models/{model_slug}
POST /api/projects/{owner_slug}/{project_slug}/models/{model_slug}/disable
POST /api/projects/{owner_slug}/{project_slug}/models/{model_slug}/enable
The create/update operation must point to a training job with a promoted artifact. Re-pointing an alias lets an owner publish a new training result without changing the client-facing model slug. The update body carries only the new job reference; the alias name and slug remain stable:
{
"training_job_id": 87
}
The owner can select this operation from the project Models screen. A retired
base or a job with no promoted artifact is rejected with 409.
Listing and pagination
Project aliases keep the legacy raw-array response when no pagination parameters are supplied. Product clients should opt into the bounded cursor contract:
GET /api/projects/{owner_slug}/{project_slug}/models?pagination=cursor&limit=25
GET /api/projects/{owner_slug}/{project_slug}/models?pagination=cursor&limit=25&cursor=<next_cursor>
Cursor responses are {data, next_cursor, total_count}. The default limit is
25 and the maximum is 100. Cursors are opaque, ordered by immutable alias id,
and must be sent back unchanged. Authorization and filters are applied before
the page, so following next_cursor reaches every alias the caller is allowed
to see.
The cross-project registry is the separate GET /api/models endpoint. It uses
the same cursor shape and 25-row default/100-row maximum; access, status
and archive visibility filters are server-side. Its totals object contains
usage rollups, not a client-derived total of registry rows.
Access
An alias can be owner-only, shared with selected accounts, or public according
to the model sharing fields. The OpenAI model list is caller-aware and only
returns aliases the bearer can invoke. A caller who cannot access a model gets
the same model_not_found response as an unknown alias; this prevents model
slug enumeration.
Serving a hosted alias
Use the alias directly:
{
"model": "support-assistant",
"messages": [{"role": "user", "content": "Hello"}]
}
The control plane resolves the alias to its owner and payer, verifies the promoted LoRA artifact, and dispatches a signed descriptor to the serving unit. A missing or invalid adapter never silently falls back to the base model.
For a stopped source job, cancelled is the terminal attempt state, not a
signal that the adapter is absent. Serving uses the promoted artifact and
model_available; a cancelled attempt without a promoted artifact is
rejected.
Deprecation
The catalog is authoritative. A fine-tune trained on a retired base is marked
deprecated: true in training/model payloads, cannot be newly published or
re-pointed, and returns 410 with error.code = "model_deprecated" when
served. Existing artifact downloads remain available so owners can migrate or
audit their data.
Project archives
Archiving is reversible and does not delete chats, jobs, aliases, or artifacts. Archived projects are read-only: writes return the regular project-archive conflict, while OpenAI inference returns:
{
"error": {
"type": "invalid_request_error",
"code": "project_archived"
}
}
The OpenAI response is 404 with no Retry-After, because an archive is a
deliberate owner action rather than a transient outage. Unarchive the project
from project settings before serving again.