v2 Endpoints
The current-format API, rooted at /api/model_references/v2. All paths below are relative to
https://models.aihorde.net/api. Read the Conventions page first for base URL,
auth, error shape, and status codes. For the text-generation grouping toolkit see
v2 Text Utilities; for the review workflow see
Pending Queue endpoints.
{category} is one of the model categories: image_generation,
text_generation, clip, controlnet, blip, esrgan, gfpgan, codeformer, safety_checker,
video_generation, audio_generation, miscellaneous, lora, ti.
Read operations
Unauthenticated and safe to cache.
| Method & path | Description |
|---|---|
GET /model_references/v2/info |
API information message. |
GET /model_references/v2/model_categories |
List all category names. |
GET /model_references/v2/{category} |
All models in a category, as {name: record}. 404 if unknown/empty. |
GET /model_references/v2/{category}/model/{model_name} |
A single model record. 404 if missing. |
GET /model_references/v2/{category}/search |
Filter/sort/paginate within a category (see Search). |
GET /model_references/v2/search |
Search across all categories. |
GET /model_references/v2/{category}/popular |
Rank by live Horde usage (image_generation, text_generation only). |
GET /model_references/v2/metadata/last_updated |
Canonical last-updated timestamp (PRIMARY, v2 only). |
GET /model_references/v2/metadata/metadata |
All categories' metadata ({category: CategoryMetadata}). |
GET /model_references/v2/metadata/{category} |
Metadata for one category. |
GET /model_references/v2/metadata/{category}/last_updated |
Last-updated timestamp for one category. |
GET /model_references/statistics/{category} |
Aggregated category statistics (see Statistics). |
GET /model_references/statistics/{category}/deletion-risk |
Usage-informed deletion-risk analysis. |
GET /model_references/v2/me/roles |
The authenticated caller's roles (requires apikey). |
Why metadata/metadata?
The all-categories route really is …/metadata/metadata -- the metadata router is mounted under a
/metadata prefix and its "everything" operation is itself named metadata. The doubling is
intentional, not a typo; the single-category route is …/metadata/{category}.
Why /{category}/model/{model_name} and not /{category}/{model_name}?
Single-model operations are nested under a literal model segment so the {model_name} parameter
has no sibling routes to compete with. The category collections that live directly under
/{category} -- search, popular, and the text_generation toolkit (aliases, families, …)
-- would otherwise shadow a model whose name happened to match one of them. With the model
segment, a model may be named anything (even search) and is always addressable at
/{category}/model/<name>.
Typed per-category routes
Every category has a concrete record type, so the read routes above also exist as typed per-category operations in the OpenAPI schema:
GET /model_references/v2/{category}documents its response as{name: <CategoryRecord>}(e.g.ImageGenerationModelRecord,ClipModelRecord).GET /model_references/v2/{category}/model/{model_name}documents its response as the concrete<CategoryRecord>.
The runtime response is the raw stored JSON (passthrough); the concrete schema exists so generated
SDK clients get a real model type instead of a union. A generic parameterized route remains as a
uniform fallback (operation ids read_v2_reference, read_v2_single_model).
Search
GET /model_references/v2/{category}/search and GET /model_references/v2/search.
| Query param | Type | Notes |
|---|---|---|
nsfw |
bool | Filter by NSFW flag. |
baseline |
str | Exact baseline match. |
inpainting |
bool | image_generation only. |
tags_any / tags_all / tags_none |
list[str] | Tag set membership. |
name_contains |
str | Case-insensitive substring. |
backend |
str | text_generation backend filter. |
exclude_backend_variations |
bool | Collapse text backend duplicates. |
quantized |
bool | text_generation only. |
sort_by |
str | Any record field. |
sort_desc |
bool | Default false. |
limit |
int | 1–500, default 50. |
offset |
int | ≥ 0, default 0. |
source |
str | horde (default, canonical), any (canonical + providers), or a provider id. |
Response is a SearchResponse envelope: { "results": [...], "total", "offset", "limit", "has_more" }.
Popular
GET /model_references/v2/{category}/popular - joins live AI-Horde worker/usage data.
| Query param | Type | Notes |
|---|---|---|
limit |
int | 1–100, default 10. |
sort_by |
enum | worker_count (default), usage_day, usage_month, usage_total. |
include_workers |
bool | Include per-worker detail. |
Only image_generation and text_generation carry usage data; other categories return an empty
list. Returns an empty list (not an error) if the upstream AI-Horde API is degraded - check
/api/heartbeat.
Statistics
GET /model_references/statistics/{category} -> a CategoryStatistics object (counts overall /
NSFW / SFW, baseline distribution, download stats, tag/style distributions, category-specific
metrics).
| Query param | Type | Notes |
|---|---|---|
group_text_models |
bool | Group text_generation variants by base name. |
limit |
int | Optional cap on returned models. |
offset |
int | ≥ 0, default 0. |
Cached (default 300 s); caching is skipped when grouping is enabled.
Deletion risk
GET /model_references/statistics/{category}/deletion-risk -> a CategoryDeletionRiskResponse
combining local data with live usage.
| Query param | Type | Notes |
|---|---|---|
group_text_models |
bool | Group text variants. |
include_backend_variations |
bool | text_generation only. |
preset |
str | One of deletion_candidates, zero_usage, no_workers, missing_data, host_issues, critical, low_usage. |
limit / offset |
int | Pagination. |
GET /model_references/v2/me/roles
Requires apikey. Returns { "user_id", "username", "roles": [...], "is_approver", "is_requestor" }.
Use it to decide which write/queue actions to offer in a client.
Write operations
All writes require PRIMARY mode, canonical_format='v2', and a requestor apikey. They
return 202 Accepted with a PendingChangeRecord and enter the pending queue;
nothing changes in the live dataset until an approver applies it. A REPLICA or a mismatched
canonical format returns 503. See Submit Models via the API.
| Method & path | Body | Description |
|---|---|---|
POST /model_references/v2/{category} |
concrete <CategoryRecord> |
Typed create. Name comes from the body. 409 if it already exists. |
PUT /model_references/v2/{category}/model/{model_name} |
concrete <CategoryRecord> |
Typed update. Path model_name must equal the body name (400 otherwise); 404 if missing. |
POST /model_references/v2/{category}/add |
ModelRecordUnion |
Generic create - a single uniform endpoint covering any category. |
DELETE /model_references/v2/{category}/model/{model_name} |
- | Delete a model. |
Notes:
- The typed routes (
POST /{category},PUT /{category}/model/{model_name}) are preferred: they expose the category's concrete request schema, so a wrong-schema body is rejected with422. - The generic
/addand the genericPUT /{category}/model/{model_name}accept a discriminated union and exist as a uniform fallback (operation idscreate_v2_model,update_v2_model,delete_v2_model). - For
text_generation, submit base model names only; backend-prefixed variants are generated automatically (submitting one returns400).text_model_groupis auto-filled if omitted.
Write status codes
| Code | When |
|---|---|
202 |
Accepted and queued. |
400 |
Path/body name mismatch, or a text_generation backend-prefixed name. |
401 |
Missing/invalid apikey, or not a requestor. |
404 |
Update/delete target does not exist. |
409 |
Create target already exists. |
422 |
Body failed validation, or unknown category. |
503 |
REPLICA mode, or canonical_format != 'v2'. |
Metadata
GET /model_references/v2/metadata/... returns per-category last_updated UNIX timestamps for
change detection (see Consume the HTTP API -> Detect changes).
These require a PRIMARY deployment whose canonical format is v2; otherwise they return 503.
See also
- v2 Text Utilities - the
text_generationgrouping/alias/family/naming toolkit. - Pending Queue endpoints - review and apply queued writes.
- Canonical Format - why writes route to one API version.