For AI agents: markdown of this page — /docs-content-en/ai/credentials/models-add.md documentation index — /llms.txt
Add a model manually
POST /v1/ai/credentials/:id/models
Connects a model to a key from any provider. Supply one modelId or a batch using modelIds (1 to 100 strings). For keys of all providers except the Custom provider, metadata priority is: request body → live list → defaults. Manual connection by model ID works if the list is unavailable. Single requests to the Custom provider keep their existing contract: any string up to 200 characters that is nonblank after trimming surrounding whitespace, with body metadata taking priority.
Requires the vibe:ai scope. The public API accepts only your own USER key. A key owned by another user, a missing key or a PORTAL key returns 404 not_found.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
Parameterid (path) |
Typestring | Requiredyes | DescriptionKey ID from GET /v1/ai/credentials |
Request fields (body)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
FieldmodelId |
Typestring | Requiredsingle only | Default— | DescriptionThe model ID at the provider without the <slug>/ prefix. The response adds the prefix; use the returned modelId as the model in requests to /v1/chat/completions |
FieldmodelIds |
Typestring[] | Requiredbatch only | Default— | Description1 to 100 provider IDs; cannot be combined with modelId |
Fieldname |
Typestring | Requiredno | Defaultvalue of modelId |
DescriptionDisplay name of the model. null uses the default value |
FieldcontextLength |
Typeinteger | Requiredno | Default4096 |
DescriptionMaximum context size in tokens. An integer from -2147483648 to 2147483647; null uses the default value |
FieldmaxOutputTokens |
Typeinteger | Requiredno | Defaultnull |
DescriptionMaximum tokens in the response. An integer from -2147483648 to 2147483647, or null |
Examples
curl — personal key
curl -X POST https://vibecode.bitrix24.com/v1/ai/credentials/cred_custom_xyz/models \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"modelId": "abab6.5-chat",
"name": "MiniMax abab6.5-chat",
"contextLength": 32768,
"maxOutputTokens": 8192
}'
curl — OAuth application
curl -X POST https://vibecode.bitrix24.com/v1/ai/credentials/cred_custom_xyz/models \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"modelId": "abab6.5-chat",
"name": "MiniMax abab6.5-chat",
"contextLength": 32768,
"maxOutputTokens": 8192
}'
JavaScript — personal key
const id = 'cred_custom_xyz'
const res = await fetch(`https://vibecode.bitrix24.com/v1/ai/credentials/${id}/models`, {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
modelId: 'abab6.5-chat',
name: 'MiniMax abab6.5-chat',
contextLength: 32768,
maxOutputTokens: 8192,
}),
})
const { data } = await res.json()
console.log('Registered model with id:', data.id)
JavaScript — OAuth application
const id = 'cred_custom_xyz'
const res = await fetch(`https://vibecode.bitrix24.com/v1/ai/credentials/${id}/models`, {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
modelId: 'abab6.5-chat',
name: 'MiniMax abab6.5-chat',
contextLength: 32768,
maxOutputTokens: 8192,
}),
})
const { data } = await res.json()
console.log('Registered model with id:', data.id)
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true on success |
Fielddata.id |
Typestring | DescriptionUnique ID of the AiModel record (needed for deletion) |
Fielddata.modelId |
Typestring | DescriptionThe registered modelId with the provider <slug>/ prefix, for example custom-openai-compat/ |
Fielddata.name |
Typestring | DescriptionModel name |
Fielddata.contextLength |
Typeinteger | DescriptionThe saved context size |
Fielddata.created[] |
Typearray | DescriptionBatch modelIds request only, response 200: connected models, each { modelId, rowId } |
Fielddata.skipped[] |
Typearray | DescriptionBatch modelIds request only, response 200: skipped models, each { modelId, reason }, where reason is already_connected |
Response example
Single modelId request, HTTP status 201 Created:
{
"success": true,
"data": {
"id": "aimodel_xyz789",
"modelId": "custom-openai-compat/abab6.5-chat",
"name": "MiniMax abab6.5-chat",
"contextLength": 32768
}
}
Batch request { "modelIds": ["gpt-4o-mini", "gpt-4o"] }, HTTP status 200 OK. The gpt-4o model was already connected to the key:
{
"success": true,
"data": {
"created": [
{ "modelId": "gpt-4o-mini", "rowId": "aimodel_xyz789" }
],
"skipped": [
{ "modelId": "gpt-4o", "reason": "already_connected" }
]
}
}
Error response example
404 not_found — the key was not found or belongs to another user:
{
"success": false,
"error": {
"code": "not_found",
"message": "Credential not found"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP400 | Codeinvalid_request |
DescriptionmodelId is missing, is not a string, is empty after trim, or the original string is longer than 200 characters |
| HTTP400 | Codeinvalid_request |
Descriptionname is provided and is neither a string nor null; the message identifies the name field |
| HTTP400 | Codeinvalid_request |
DescriptioncontextLength or maxOutputTokens is provided and is neither an integer from -2147483648 to 2147483647 nor null; the message identifies the invalid field |
| HTTP400 | Codeinvalid_request |
DescriptionBoth modelId and modelIds are provided |
| HTTP400 | Codeinvalid_request |
DescriptionmodelIds is not an array, is empty, or contains more than 100 IDs |
| HTTP400 | Codeinvalid_request |
DescriptionAn ID for a provider other than the Custom provider contains characters outside [A-Za-z0-9._:/@-] |
| HTTP400 | Codeno_key |
DescriptionThe stored key has no API key value |
| HTTP400 | Codebase_url_redirect |
DescriptionThe provider answered the model list request with a forbidden redirect |
| HTTP403 | Codescope_missing |
DescriptionThe API key lacks the vibe:ai scope |
| HTTP404 | Codenot_found |
DescriptionA key with this id was not found or does not belong to you |
| HTTP409 | Codekey_models_limit |
DescriptionThe key would exceed 1000 model rows. Nothing from the batch is saved |
| HTTP409 | Codealready_exists |
DescriptionA model with the same modelId is already registered for this key |
| HTTP429 | Codemodel_discovery_busy |
DescriptionAnother model list request is already running |
| HTTP429 | Codemodel_discovery_rate_limit |
DescriptionThe shared limit of 10 model list requests per minute is reached |
| HTTP500 | Codedecryption_error |
DescriptionThe stored credential cannot be decrypted |
For the full list of common API errors, see Errors.
Model registration limit: 30 requests per minute. The current limit is returned in the x-ratelimit-limit header.
Known specifics
Price is zero. Key models are always registered with a zero price (inputPrice = 0, outputPrice = 0). The platform does not bill such records — you pay the provider directly.
Batch connection. Supply { "modelIds": ["gpt-4o-mini", "gpt-4o"] } without modelId. The entire batch is validated before writing. IDs for providers other than the Custom provider use only [A-Za-z0-9._:/@-], up to 200 characters. One snapshot of the list is used for the whole batch. Response 200: created contains { modelId, rowId }, skipped contains { modelId, reason: "already_connected" }. In a batch response, modelId is the raw provider ID. Duplicates and concurrent requests for the same model appear in skipped.
A key holds at most 1000 rows. Exceeding this returns 409 key_models_limit without partial batch writes. A single duplicate returns 409 already_exists, and a successful single request still returns 201. A new row inherits capabilities and reasoningControl from the platform model with the same ID. If there is no such row, capabilities from the provider list are used.
Model list request limits. They are shared by available-models, fetch-models and connection: 20 seconds including all retries and pages, up to 5 MiB per response before JSON parsing, and at most 1000 models and 10 pages. A repeated cursor stops pagination. Only one such request runs per account at a time, and at most 10 run per minute. Incomplete lists never change absent models to DEPRECATED.