ClouisleClouisle

Models API

Discover and manage LLM models

Endpoints

MethodPathPurposeAuth
GET/api/v1/models/providersGet supported LLM providersNone
GET/api/v1/models/typesGet supported model typesNone
GET/api/v1/models/availableGet enabled models for dropdownJWT
GET/api/v1/models/default/{model_type}Get default model for a typeJWT
GET/api/v1/admin/modelsPaginated list of all configured modelsadmin:model:read
GET/api/v1/admin/models/{model_id}Get single model detailsadmin:model:read
POST/api/v1/admin/modelsCreate a new modeladmin:model:create
PUT/api/v1/admin/models/{model_id}Update model configurationadmin:model:update
DELETE/api/v1/admin/models/{model_id}Delete a modeladmin:model:delete
POST/api/v1/admin/models/{model_id}/set-defaultSet as default modeladmin:model:update
POST/api/v1/admin/models/{model_id}/testTest saved model connectivityadmin:model:update
POST/api/v1/admin/models/testTest model config (no save)admin:model:create
POST/api/v1/admin/models/discoverDiscover provider available modelsadmin: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/providers

No 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):

codenameDefault base_url
openaiOpenAIhttps://api.openai.com/v1
openai_responsesOpenAI Responseshttps://api.openai.com/v1
anthropicAnthropichttps://api.anthropic.com
googleGoogle AIhttps://generativelanguage.googleapis.com/v1beta
azure_openaiAzure OpenAInull
deepseekDeepSeekhttps://api.deepseek.com
moonshotMoonshothttps://api.moonshot.cn/v1
zhipuZhipu AIhttps://open.bigmodel.cn/api/paas/v4
qwenQwenhttps://dashscope.aliyuncs.com/compatible-mode/v1
baichuanBaichuanhttps://api.baichuan-ai.com/v1
minimaxMiniMaxhttps://api.minimax.chat/v1
volcengineVolcenginehttps://ark.cn-beijing.volces.com/api/v3
siliconflowSiliconFlowhttps://api.siliconflow.cn/v1
xaixAI (Grok)https://api.x.ai/v1
ollamaOllamahttp://localhost:11434
runwayRunwayhttps://api.dev.runwayml.com
pikaPikahttps://api.pika.art/v1
lumaLuma AIhttps://api.lumalabs.ai/dream-machine/v1
klingKlinghttps://api.klingai.com
stabilityStability AIhttps://api.stability.ai
midjourneyMidjourneynull
typesafeTypeSafe AIhttps://api.typesafe.ai/v1
customOpenAI Compatiblenull
FieldTypeDescription
codestringProvider identifier
namestringDisplay name
base_urlstringDefault API base URL (null when there is no default, e.g. azure_openai, midjourney, custom)
iconstringIcon 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/types

No 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/available

Requires JWT authentication. Returns a list of enabled models, usable for dropdown selection.

Query ParameterTypeRequiredDefaultDescription
model_typestringNo-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 ParameterTypeRequiredDescription
model_typestringYesModel 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

ScopeDescription
admin:model:readList and view models
admin:model:createCreate and test new models
admin:model:updateUpdate models, set defaults, test saved models
admin:model:deleteDelete models

List Models

GET /api/v1/admin/models

Requires admin:model:read permission. Returns a paginated list of all configured models.

Query ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number
page_sizeintegerNo20Items per page (max: 100)
providerarrayNo-Filter by provider (repeatable)
model_typearrayNo-Filter by model type (repeatable)
is_enabledbooleanNo-Filter by enabled status
searchstringNo-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:

FieldTypeDescription
idstringModel UUID
namestringDisplay name
providerstringProvider identifier
provider_display_namestringOptional user-facing provider/gateway name
model_idstringModel identifier (e.g. gpt-4-turbo-preview)
model_typestringModel type: chat, embedding, rerank, decision, tts, stt, audio_generation, text_to_image, text_to_video
base_urlstringCustom API URL
has_api_keybooleanWhether an API key is configured (key itself is hidden)
context_lengthintegerContext length
max_output_tokensintegerMax output tokens
input_pricenumberInput price per 1M tokens
output_pricenumberOutput price per 1M tokens
default_paramsobjectDefault inference parameters
capabilitiesobjectModel capabilities (e.g. streaming, function_calling, vision)
configobjectAdditional provider-specific configuration
is_enabledbooleanEnabled status
is_defaultbooleanWhether this is the default model for its type
sort_orderintegerSort order
created_atstringISO 8601 timestamp
updated_atstringISO 8601 timestamp

Get Model

GET /api/v1/admin/models/{model_id}

Requires admin:model:read permission.

Path ParameterTypeRequiredDescription
model_idstringYesModel 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/models

Requires admin:model:create permission.

Request Body Fields:

FieldTypeRequiredDescription
namestringYesDisplay name (max 100 chars)
providerstringYesProvider identifier (must be a supported provider)
model_idstringYesModel identifier (max 100 chars)
model_typestringYesModel type; decision requires the typesafe provider and embedding is also restricted to specific providers — a mismatch returns 1001 model_type_not_supported
provider_display_namestringNoOptional user-facing provider or gateway name
base_urlstringNoCustom API URL (max 512 chars)
api_keystringNoAPI key (optional for local providers)
context_lengthintegerNoContext length
max_output_tokensintegerNoMax output tokens
input_pricenumberNoInput price per 1M tokens
output_pricenumberNoOutput price per 1M tokens
default_paramsobjectNoDefault inference parameters
capabilitiesobjectNoModel capabilities
configobjectNoAdditional configuration
is_enabledbooleanNoEnabled status (default: true)
is_defaultbooleanNoDefault model flag (default: false)
sort_orderintegerNoSort 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 ParameterTypeRequiredDescription
model_idstringYesModel 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 ParameterTypeRequiredDescription
model_idstringYesModel 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-default

Requires admin:model:update permission. Sets the specified model as the default for its type.

Path ParameterTypeRequiredDescription
model_idstringYesModel 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}/test

Requires admin:model:update permission. Tests connectivity for an already-saved model. No request body required.

Path ParameterTypeRequiredDescription
model_idstringYesModel 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/test

Requires 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/discover

Requires 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:

providerDiscovery pathAuthentication
openai, openai_responses, anthropic, baichuan, minimax, siliconflow, xai, custom/v1/modelsAuthorization: Bearer <api_key>
deepseek/modelsAuthorization: Bearer <api_key>
google/v1beta/modelsQuery parameter key=<api_key>
zhipu/api/paas/v4/modelsAuthorization: Bearer <api_key>
qwen/compatible-mode/v1/modelsAuthorization: Bearer <api_key>
volcengine/api/v3/modelsAuthorization: Bearer <api_key>
ollama/api/tagsNo key required
typesafeSee the note belowAuthorization: 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

CodeMessageDescription
6100Model not foundModel does not exist
6101Team model not foundTeam model authorization does not exist
6102Team model existsTeam model authorization already exists
6103Model quota exceededTeam model quota exceeded
3000Permission deniedInsufficient permissions
1001Validation failedInvalid 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);

How is this guide?

On this page