Models API
Discover and manage LLM models
Endpoints
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET | /api/v1/models/providers | Get supported LLM providers | None |
| GET | /api/v1/models/types | Get supported model types | None |
| GET | /api/v1/models/available | Get enabled models for dropdown | JWT |
| GET | /api/v1/models/default/{model_type} | Get default model for a type | JWT |
| GET | /api/v1/admin/models | Paginated list of all configured models | admin:model:read |
| GET | /api/v1/admin/models/{model_id} | Get single model details | admin:model:read |
| POST | /api/v1/admin/models | Create a new model | admin:model:create |
| PUT | /api/v1/admin/models/{model_id} | Update model configuration | admin:model:update |
| DELETE | /api/v1/admin/models/{model_id} | Delete a model | admin:model:delete |
| POST | /api/v1/admin/models/{model_id}/set-default | Set as default model | admin:model:update |
| POST | /api/v1/admin/models/{model_id}/test | Test saved model connectivity | admin:model:update |
| POST | /api/v1/admin/models/test | Test model config (no save) | admin:model:create |
| POST | /api/v1/admin/models/discover | Discover provider available models | admin:model:create |
/api/v1/admin/models/* are protected endpoints used by the admin console, requiring the corresponding administrator permission scopes.
Public Catalog Endpoints
These endpoints are used to discover available providers and models, without requiring administrator permissions.
List Providers
GET /api/v1/models/providersNo authentication required. Returns all 23 providers supported by the system with their default configuration.
curl -X GET "https://your-domain.com/api/v1/models/providers"Success Response (200 OK, excerpt):
{
"code": 0,
"data": [
{
"code": "openai",
"name": "OpenAI",
"base_url": "https://api.openai.com/v1",
"icon": "openai"
},
{
"code": "openai_responses",
"name": "OpenAI Responses",
"base_url": "https://api.openai.com/v1",
"icon": "openai"
},
{
"code": "anthropic",
"name": "Anthropic",
"base_url": "https://api.anthropic.com",
"icon": "anthropic"
},
{
"code": "typesafe",
"name": "TypeSafe AI",
"base_url": "https://api.typesafe.ai/v1",
"icon": "typesafe"
}
],
"msg": "success"
}Full provider list (code is the provider value to use when creating a model):
code | name | Default base_url |
|---|---|---|
openai | OpenAI | https://api.openai.com/v1 |
openai_responses | OpenAI Responses | https://api.openai.com/v1 |
anthropic | Anthropic | https://api.anthropic.com |
google | Google AI | https://generativelanguage.googleapis.com/v1beta |
azure_openai | Azure OpenAI | null |
deepseek | DeepSeek | https://api.deepseek.com |
moonshot | Moonshot | https://api.moonshot.cn/v1 |
zhipu | Zhipu AI | https://open.bigmodel.cn/api/paas/v4 |
qwen | Qwen | https://dashscope.aliyuncs.com/compatible-mode/v1 |
baichuan | Baichuan | https://api.baichuan-ai.com/v1 |
minimax | MiniMax | https://api.minimax.chat/v1 |
volcengine | Volcengine | https://ark.cn-beijing.volces.com/api/v3 |
siliconflow | SiliconFlow | https://api.siliconflow.cn/v1 |
xai | xAI (Grok) | https://api.x.ai/v1 |
ollama | Ollama | http://localhost:11434 |
runway | Runway | https://api.dev.runwayml.com |
pika | Pika | https://api.pika.art/v1 |
luma | Luma AI | https://api.lumalabs.ai/dream-machine/v1 |
kling | Kling | https://api.klingai.com |
stability | Stability AI | https://api.stability.ai |
midjourney | Midjourney | null |
typesafe | TypeSafe AI | https://api.typesafe.ai/v1 |
custom | OpenAI Compatible | null |
| Field | Type | Description |
|---|---|---|
code | string | Provider identifier |
name | string | Display name |
base_url | string | Default API base URL (null when there is no default, e.g. azure_openai, midjourney, custom) |
icon | string | Icon identifier |
openai_responses speaks the OpenAI Responses API (not Chat Completions), typesafe backs decision-type models, and custom represents any OpenAI-compatible endpoint.
List Model Types
GET /api/v1/models/typesNo authentication required. Returns all model types supported by the system.
curl -X GET "https://your-domain.com/api/v1/models/types"Success Response (200 OK):
{
"code": 0,
"data": [
{ "code": "chat", "name": "Chat", "description": "对话模型" },
{ "code": "embedding", "name": "Embedding", "description": "嵌入模型" },
{ "code": "rerank", "name": "Rerank", "description": "重排序模型" },
{ "code": "tts", "name": "TTS", "description": "语音合成" },
{ "code": "stt", "name": "STT", "description": "语音识别" },
{ "code": "audio_generation", "name": "Audio Generation", "description": "音频生成" },
{ "code": "text_to_image", "name": "Text to Image", "description": "文生图" },
{ "code": "text_to_video", "name": "Text to Video", "description": "文生视频" },
{ "code": "decision", "name": "Decision", "description": "决策模型" }
],
"msg": "success"
}decision is a non-generative typed-decision type (choice/score/yes-no judgments) and is only available from the typesafe provider; creating a decision model with any other provider returns 1001 model_type_not_supported.
List Available Models
GET /api/v1/models/availableRequires JWT authentication. Returns a list of enabled models, usable for dropdown selection.
| Query Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
model_type | string | No | - | Filter by model type (e.g. chat, embedding) |
curl -X GET "https://your-domain.com/api/v1/models/available?model_type=chat" \
-H "Authorization: Bearer YOUR_TOKEN"Success Response (200 OK):
{
"code": 0,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "GPT-4 Turbo",
"provider": "openai",
"provider_display_name": null,
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"capabilities": {
"streaming": true,
"function_calling": true
}
}
],
"msg": "success"
}Get Default Model
GET /api/v1/models/default/{model_type}Requires JWT authentication. Returns the default enabled model for the specified type.
| Path Parameter | Type | Required | Description |
|---|---|---|---|
model_type | string | Yes | Model type (e.g. chat, embedding) |
curl -X GET "https://your-domain.com/api/v1/models/default/chat" \
-H "Authorization: Bearer YOUR_TOKEN"Success Response (200 OK):
Returns a single ModelBrief object (same structure as available model list items), or null if no default exists.
{
"code": 0,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "GPT-4 Turbo",
"provider": "openai",
"provider_display_name": null,
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"capabilities": {
"streaming": true,
"function_calling": true
}
},
"msg": "success"
}Admin Endpoints
These endpoints are used to manage model configurations, requiring the corresponding administrator permission scopes.
Permission Scopes
| Scope | Description |
|---|---|
admin:model:read | List and view models |
admin:model:create | Create and test new models |
admin:model:update | Update models, set defaults, test saved models |
admin:model:delete | Delete models |
List Models
GET /api/v1/admin/modelsRequires admin:model:read permission. Returns a paginated list of all configured models.
| Query Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 1 | Page number |
page_size | integer | No | 20 | Items per page (max: 100) |
provider | array | No | - | Filter by provider (repeatable) |
model_type | array | No | - | Filter by model type (repeatable) |
is_enabled | boolean | No | - | Filter by enabled status |
search | string | No | - | Search by name or model ID |
curl -X GET "https://your-domain.com/api/v1/admin/models?page=1&page_size=20" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"Success Response (200 OK):
{
"code": 0,
"data": {
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "GPT-4 Turbo",
"provider": "openai",
"provider_display_name": null,
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"base_url": "https://api.openai.com/v1",
"has_api_key": true,
"context_length": 128000,
"max_output_tokens": 4096,
"input_price": 0.01,
"output_price": 0.03,
"default_params": {
"temperature": 0.7
},
"capabilities": {
"streaming": true,
"function_calling": true,
"vision": false
},
"config": {},
"is_enabled": true,
"is_default": true,
"sort_order": 0,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-02-11T15:30:00Z"
}
],
"total": 12,
"page": 1,
"page_size": 20
},
"msg": "success"
}Response Fields:
| Field | Type | Description |
|---|---|---|
id | string | Model UUID |
name | string | Display name |
provider | string | Provider identifier |
provider_display_name | string | Optional user-facing provider/gateway name |
model_id | string | Model identifier (e.g. gpt-4-turbo-preview) |
model_type | string | Model type: chat, embedding, rerank, decision, tts, stt, audio_generation, text_to_image, text_to_video |
base_url | string | Custom API URL |
has_api_key | boolean | Whether an API key is configured (key itself is hidden) |
context_length | integer | Context length |
max_output_tokens | integer | Max output tokens |
input_price | number | Input price per 1M tokens |
output_price | number | Output price per 1M tokens |
default_params | object | Default inference parameters |
capabilities | object | Model capabilities (e.g. streaming, function_calling, vision) |
config | object | Additional provider-specific configuration |
is_enabled | boolean | Enabled status |
is_default | boolean | Whether this is the default model for its type |
sort_order | integer | Sort order |
created_at | string | ISO 8601 timestamp |
updated_at | string | ISO 8601 timestamp |
Get Model
GET /api/v1/admin/models/{model_id}Requires admin:model:read permission.
| Path Parameter | Type | Required | Description |
|---|---|---|---|
model_id | string | Yes | Model UUID |
curl -X GET "https://your-domain.com/api/v1/admin/models/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"Success Response (200 OK): Returns a single ModelResponse object (same structure as list items).
Error Response (404 Not Found):
{
"code": 6100,
"data": null,
"msg": "Model not found"
}Create Model
POST /api/v1/admin/modelsRequires admin:model:create permission.
Request Body Fields:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name (max 100 chars) |
provider | string | Yes | Provider identifier (must be a supported provider) |
model_id | string | Yes | Model identifier (max 100 chars) |
model_type | string | Yes | Model type; decision requires the typesafe provider and embedding is also restricted to specific providers — a mismatch returns 1001 model_type_not_supported |
provider_display_name | string | No | Optional user-facing provider or gateway name |
base_url | string | No | Custom API URL (max 512 chars) |
api_key | string | No | API key (optional for local providers) |
context_length | integer | No | Context length |
max_output_tokens | integer | No | Max output tokens |
input_price | number | No | Input price per 1M tokens |
output_price | number | No | Output price per 1M tokens |
default_params | object | No | Default inference parameters |
capabilities | object | No | Model capabilities |
config | object | No | Additional configuration |
is_enabled | boolean | No | Enabled status (default: true) |
is_default | boolean | No | Default model flag (default: false) |
sort_order | integer | No | Sort order (default: 0) |
curl -X POST "https://your-domain.com/api/v1/admin/models" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "GPT-4 Turbo",
"provider": "openai",
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"base_url": "https://api.openai.com/v1",
"api_key": "sk-...",
"is_enabled": true
}'Success Response (200 OK):
{
"code": 0,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "GPT-4 Turbo",
"provider": "openai",
"provider_display_name": null,
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"base_url": "https://api.openai.com/v1",
"has_api_key": true,
"context_length": null,
"max_output_tokens": null,
"input_price": null,
"output_price": null,
"default_params": null,
"capabilities": null,
"config": null,
"is_enabled": true,
"is_default": false,
"sort_order": 0,
"created_at": "2026-02-11T16:00:00Z",
"updated_at": "2026-02-11T16:00:00Z"
},
"msg": "Model created successfully"
}Update Model
PUT /api/v1/admin/models/{model_id}Requires admin:model:update permission. All fields are optional; only include fields you want to update.
| Path Parameter | Type | Required | Description |
|---|---|---|---|
model_id | string | Yes | Model UUID |
curl -X PUT "https://your-domain.com/api/v1/admin/models/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "GPT-4 Turbo (Updated)",
"default_params": {
"temperature": 0.8
}
}'Success Response (200 OK):
{
"code": 0,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "GPT-4 Turbo (Updated)",
"provider": "openai",
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"is_enabled": true,
"updated_at": "2026-02-11T16:05:00Z"
},
"msg": "Model updated successfully"
}Delete Model
DELETE /api/v1/admin/models/{model_id}Requires admin:model:delete permission. Permanently deletes the model.
| Path Parameter | Type | Required | Description |
|---|---|---|---|
model_id | string | Yes | Model UUID |
curl -X DELETE "https://your-domain.com/api/v1/admin/models/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"Success Response (200 OK):
{
"code": 0,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "GPT-4 Turbo (Updated)",
"provider": "openai",
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"is_enabled": true,
"updated_at": "2026-02-11T16:05:00Z"
},
"msg": "Model deleted successfully"
}Set Default Model
POST /api/v1/admin/models/{model_id}/set-defaultRequires admin:model:update permission. Sets the specified model as the default for its type.
| Path Parameter | Type | Required | Description |
|---|---|---|---|
model_id | string | Yes | Model UUID |
curl -X POST "https://your-domain.com/api/v1/admin/models/550e8400-e29b-41d4-a716-446655440000/set-default" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"Success Response (200 OK): Returns the updated ModelResponse with is_default: true.
Test Saved Model
POST /api/v1/admin/models/{model_id}/testRequires admin:model:update permission. Tests connectivity for an already-saved model. No request body required.
| Path Parameter | Type | Required | Description |
|---|---|---|---|
model_id | string | Yes | Model UUID |
curl -X POST "https://your-domain.com/api/v1/admin/models/550e8400-e29b-41d4-a716-446655440000/test" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"Success Response (200 OK):
{
"code": 0,
"data": {
"success": true,
"message": "Model connection successful",
"latency_ms": 1200
},
"msg": "Model test successful"
}Error Response (500 Internal Server Error):
{
"code": 6100,
"data": null,
"msg": "Model test failed"
}Test Model Configuration (No Save)
POST /api/v1/admin/models/testRequires admin:model:create permission. Tests a provider/model configuration before saving it.
{
"provider": "openai",
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"base_url": "https://api.openai.com/v1",
"api_key": "sk-...",
"default_params": {
"temperature": 0.7
},
"config": {}
}curl -X POST "https://your-domain.com/api/v1/admin/models/test" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "openai",
"model_id": "gpt-4-turbo-preview",
"model_type": "chat",
"api_key": "sk-..."
}'Success Response (200 OK):
{
"code": 0,
"data": {
"success": true,
"message": "Model connection successful",
"latency_ms": 1100
},
"msg": "Model test successful"
}Decision-model test behavior
When model_type is decision, both test endpoints build a built-in decision request (a state describing a support scenario and one noul-type question) and call the provider through the Decision adapter; the test succeeds only if the answer set is non-empty, otherwise it returns 1001 model_test_empty_decision_result. decision is only supported by the typesafe provider; any other provider is rejected first with 1001 model_type_not_supported.
POST /api/v1/admin/models/test checks the endpoint policy (SSRF allowlist) before testing. A custom base_url that is not allowlisted is rejected outright instead of being called.
Discover Provider Models
POST /api/v1/admin/models/discoverRequires admin:model:create permission. Lists models exposed by a provider without persisting the supplied key.
{
"provider": "openai",
"base_url": "https://api.openai.com/v1",
"api_key": "sk-..."
}Supported discovery providers and request paths:
provider | Discovery path | Authentication |
|---|---|---|
openai, openai_responses, anthropic, baichuan, minimax, siliconflow, xai, custom | /v1/models | Authorization: Bearer <api_key> |
deepseek | /models | Authorization: Bearer <api_key> |
google | /v1beta/models | Query parameter key=<api_key> |
zhipu | /api/paas/v4/models | Authorization: Bearer <api_key> |
qwen | /compatible-mode/v1/models | Authorization: Bearer <api_key> |
volcengine | /api/v3/models | Authorization: Bearer <api_key> |
ollama | /api/tags | No key required |
typesafe | See the note below | Authorization: Bearer <api_key> |
The typesafe path is derived from the configured base_url: if the base URL's path ends with /v1, /models is appended to that path (giving <configured path>/models); if the base URL has some other non-empty path, the full /v1/models path is appended to it; otherwise the default /v1/models is used. TypeSafe discovery therefore hits the configured base path, not a fixed /v1/models.
Unsupported providers return model_discovery_not_supported; an invalid base_url or one outside the SSRF allowlist returns model_discovery_base_url_invalid or model_endpoint_not_allowlisted; a required key that is missing returns model_discovery_api_key_required. Failures still use HTTP 200 with data.success set to false.
Success Response (200 OK):
{
"code": 0,
"data": {
"success": true,
"message": "Discovered 3 models",
"models": [
{
"id": "gpt-4-turbo-preview",
"name": "GPT-4 Turbo",
"context_length": 128000,
"max_output_tokens": 4096,
"capabilities": {
"streaming": true,
"function_calling": true
}
}
]
},
"msg": "success"
}Error Codes
| Code | Message | Description |
|---|---|---|
6100 | Model not found | Model does not exist |
6101 | Team model not found | Team model authorization does not exist |
6102 | Team model exists | Team model authorization already exists |
6103 | Model quota exceeded | Team model quota exceeded |
3000 | Permission denied | Insufficient permissions |
1001 | Validation failed | Invalid request data |
No per-endpoint rate limits are implemented. There is no rate-limit middleware on these endpoints.
Best Practices
Model Configuration
✅ Do:
- Test models after configuration
- Set appropriate pricing information
- Use descriptive model names
- Keep API keys secure
- Set reasonable default parameters
❌ Don't:
- Expose API keys in logs
- Use production keys in development
- Forget to update pricing
- Enable untested models
Provider Selection
✅ Do:
- Choose models based on use case
- Consider cost vs. performance
- Test multiple providers
- Monitor model availability
- Plan for provider failover
❌ Don't:
- Use single provider for all tasks
- Ignore model limitations
Code Examples
Python
import requests
def list_available_models(token, model_type="chat"):
"""List enabled models of a type."""
url = "https://your-domain.com/api/v1/models/available"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers, params={"model_type": model_type})
result = response.json()
if result['code'] == 0:
return result['data']
else:
raise Exception(f"Error: {result['msg']}")
def create_model(token, name, model_id, provider, model_type, api_key):
"""Create a new model (admin)."""
url = "https://your-domain.com/api/v1/admin/models"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
data = {
"name": name,
"provider": provider,
"model_id": model_id,
"model_type": model_type,
"api_key": api_key
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
if result['code'] == 0:
return result['data']
else:
raise Exception(f"Error: {result['msg']}")
def test_model(token, model_id):
"""Test a saved model (admin)."""
url = f"https://your-domain.com/api/v1/admin/models/{model_id}/test"
headers = {"Authorization": f"Bearer {token}"}
response = requests.post(url, headers=headers)
result = response.json()
if result['code'] == 0:
return result['data']
else:
raise Exception(f"Error: {result['msg']}")
# Usage
models = list_available_models("YOUR_TOKEN", "chat")
for model in models:
print(f"Model: {model['name']} ({model['provider']})")
# Create model (admin)
new_model = create_model(
"YOUR_ADMIN_TOKEN",
"GPT-4 Turbo",
"gpt-4-turbo-preview",
"openai",
"chat",
"sk-..."
)
print(f"Created model: {new_model['id']}")
# Test model (admin)
test_result = test_model("YOUR_ADMIN_TOKEN", new_model['id'])
print(f"Test success: {test_result['success']}")JavaScript
async function listAvailableModels(token, modelType = 'chat') {
const response = await fetch(
`https://your-domain.com/api/v1/models/available?model_type=${modelType}`,
{ headers: { 'Authorization': `Bearer ${token}` } }
);
const result = await response.json();
if (result.code === 0) {
return result.data;
} else {
throw new Error(result.msg);
}
}
async function createModel(token, name, modelId, provider, modelType, apiKey) {
const response = await fetch(
'https://your-domain.com/api/v1/admin/models',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: name,
provider: provider,
model_id: modelId,
model_type: modelType,
api_key: apiKey,
}),
}
);
const result = await response.json();
if (result.code === 0) {
return result.data;
} else {
throw new Error(result.msg);
}
}
// Usage
const models = await listAvailableModels('YOUR_TOKEN', 'chat');
models.forEach(model => {
console.log(`Model: ${model.name} (${model.provider})`);
});
// Create model (admin)
const newModel = await createModel(
'YOUR_ADMIN_TOKEN',
'GPT-4 Turbo',
'gpt-4-turbo-preview',
'openai',
'chat',
'sk-...'
);
console.log('Created model:', newModel.id);Related Documentation
- Authentication - Authentication methods
- Model Management - Admin guide
- Agent Configuration - Using models with agents
How is this guide?