
## Add a model manually

`POST /v1/ai/credentials/:id/models`

Registers a single model bound to a Custom key. Used for providers that do not expose a catalog via `GET /v1/models` (Minimax, a corporate `vLLM`/`Ollama`, Cohere). The endpoint works only with the `custom-openai-compat` provider.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|----------|
| `id` (path) | string | yes | Custom key ID from [`GET /v1/ai/credentials`](./list.md) |

## Request fields (body)

| Field | Type | Required | Default | Description |
|------|-----|:-----:|-----------|----------|
| `modelId` | string | yes | — | The model ID at the provider. Used as the `model` in requests to [`/v1/chat/completions`](/docs/ai/chat/completions) |
| `name` | string | no | value of `modelId` | Display name of the model |
| `contextLength` | number | no | `8192` | Maximum context size in tokens |
| `maxOutputTokens` | number | no | `4096` | Maximum tokens in the response |

## Examples

### curl — personal key

```bash
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

```bash
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

```javascript
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

```javascript
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' }),
})

const { data } = await res.json()
console.log('Done:', data.modelId)
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success |
| `data.id` | string | Unique ID of the `AiModel` record (needed for [deletion](./models-delete.md)) |
| `data.modelId` | string | The registered `modelId` |
| `data.name` | string | Model name |
| `data.contextLength` | number | The saved context size |

## Response example

HTTP status `201 Created`:

```json
{
  "success": true,
  "data": {
    "id": "aimodel_xyz789",
    "modelId": "abab6.5-chat",
    "name": "MiniMax abab6.5-chat",
    "contextLength": 32768
  }
}
```

## Error response example

`400 not_custom_provider` — the key does not belong to a Custom provider:

```json
{
  "success": false,
  "error": {
    "code": "not_custom_provider",
    "message": "Manual model registration is only available for custom-openai-compat provider"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `invalid_request` | The `modelId` field was not passed or the schema is violated |
| 400 | `not_custom_provider` | The endpoint works only with the `custom-openai-compat` provider |
| 404 | `not_found` | A key with this `id` was not found or does not belong to you |
| 403 | `scope_missing` | The API key lacks the `vibe:ai` scope |

Full list of common API errors — [Errors](/docs/errors).

Model registration limit: 30 requests per minute.

## Known specifics

**Idempotent.** A repeat call with the same `modelId` updates the existing record (the `name`, `contextLength`, `maxOutputTokens` fields) instead of creating a duplicate.

**`modelId` matches the provider's.** Pass exactly the identifier the provider expects in the request `model`. For example, for Minimax — `abab6.5-chat`, and for a corporate `vLLM` — the name the model was loaded under.

**Price is zero.** Custom-provider models are always registered with a zero price (`inputPrice = 0`, `outputPrice = 0`). Platform billing skips such records — you pay the provider directly.

## See also

- [Fetch the model catalog](./fetch-models.md)
- [Key model list](./models-list.md)
- [Delete a key model](./models-delete.md)
- [Create a chat completion](/docs/ai/chat/completions)
