> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update the Devin Desktop Model Allowlist

> Replace your team's Devin Desktop model allowlist programmatically: set the allowed model UIDs and tags with an ETag check against the current state.

## Overview

Replaces your team's model allowlist, the same setting admins manage under organization controls in Devin Desktop. The request body is the full desired state: the two lists overwrite the stored ones.

To avoid overwriting a change you have not seen, the request must carry the `ETag` of a [List Models](/desktop/accounts/api-reference/list-models) response in `If-Match`. If the allowlist, the available models, or their prices changed since that response, the update is rejected with `412` and you should list the models again.

> [!NOTE]
>
> This endpoint is in alpha (`v2alpha`). The request and response shape may change.

## Authentication

Pass an API key in the `Authorization` header:

```
Authorization: Bearer <api-key>
```

Use a Devin [service user API key](/api-reference/authentication) (`cog_...`). In addition to the **Use Devin Desktop** permission that [List Models](/desktop/accounts/api-reference/list-models) requires, the service user's role must have the **Windsurf admin** permission (`account.windsurf.admin`), which the built-in Account Admin role includes. A service user without it can list models but gets `403` on this endpoint.

## Request

**If-Match** `string` *required*

The `ETag` header of a `GET /api/v2alpha/models` response reflecting the current state. Required; `*` is not accepted.

**allowed\_model\_uids** `string[]` *required*

Model UIDs users may pick, e.g. `["claude-sonnet-4-5"]`. Pass `[]` to allow models by tag only.

**allowed\_model\_tags** `string[]` *required*

Model tags users may pick, including provider tags such as `provider-anthropic` or `provider-openai`. Pass `[]` to allow only the listed model UIDs.

Both fields are required. Unknown fields are rejected.

### Example Request

```bash theme={null}
ETAG=$(curl -s -D - -o /dev/null https://server.codeium.com/api/v2alpha/models \
  -H "Authorization: Bearer $DEVIN_API_KEY" | awk 'tolower($1)=="etag:" {print $2}' | tr -d '\r')

curl -X PUT https://server.codeium.com/api/v2alpha/models \
  -H "Authorization: Bearer $DEVIN_API_KEY" \
  -H "If-Match: $ETAG" \
  -H "Content-Type: application/json" \
  -d '{"allowed_model_uids": ["claude-sonnet-4-5"], "allowed_model_tags": ["provider-anthropic"]}'
```

## Response

On success the response is the same as [List Models](/desktop/accounts/api-reference/list-models) with the new allowlist applied: every model with its `allowed` flag, the stored `allowed_model_uids` and `allowed_model_tags`, and a new `ETag` header.

## Error Responses

Errors are returned as `{"error": "<message>"}`.

| Status | Cause |
| - | - |
| `400` | Body is not JSON, has unknown fields, or is missing `allowed_model_uids` or `allowed_model_tags`; or the `filter` query parameter is set (it is accepted only by [List Models](/desktop/accounts/api-reference/list-models)) |
| `401` | Missing or invalid API key, or a legacy Windsurf API key (only Devin `cog_...` service user keys are accepted) |
| `403` | The key's user doesn't have Devin Desktop access, or its role lacks the Windsurf admin permission (`account.windsurf.admin`) |
| `412` | `If-Match` doesn't match the current `ETag`; list the models again and retry |
| `428` | `If-Match` header missing |
| `429` | Rate limit exceeded; wait for the `Retry-After` header before retrying |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.