## Set or remove a tag

`POST /v1/apps/:id/sources/:versionId/tag`

Adds or removes a single tag on a version without touching the others. Unlike [Update version metadata](/docs/source-storage/metadata-update), which replaces the whole list, this operation changes exactly one element.

Two tags are recognized, and both protect the version from automatic cleanup:

- `manual` — the version is pinned manually by an operator.
- `published` — the version is marked as published. This tag is also set automatically after `POST /v1/apps/:id/publish`.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|----------|
| `id` (path) | UUID | yes | Application identifier. Get it via [`GET /v1/apps`](/docs/apps/list). |
| `versionId` (path) | string | yes | Version identifier of the form `v<N>`. Get it via [List versions](/docs/source-storage/versions). |

## Request fields (body)

| Field | Type | Required | Description |
|------|-----|:-----:|----------|
| `tag` | string | yes | `manual` or `published`. |
| `action` | string | yes | `add` — add the tag, `remove` — remove it. |

## Examples

### curl — personal key

```bash
curl -X POST https://vibecode.bitrix24.com/v1/apps/<APP_ID>/sources/v3/tag \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tag": "manual", "action": "add" }'
```

### curl — OAuth application

```bash
curl -X POST https://vibecode.bitrix24.com/v1/apps/<APP_ID>/sources/v3/tag \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "tag": "manual", "action": "add" }'
```

### JavaScript — personal key

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/apps/${appId}/sources/v3/tag`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ tag: 'manual', action: 'add' }),
  },
)
const { data } = await res.json()
console.log('Version tags:', data.tags)
```

### JavaScript — OAuth application

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/apps/${appId}/sources/v3/tag`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ tag: 'manual', action: 'add' }),
  },
)
const { data } = await res.json()
console.log('Version tags:', data.tags)
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success. |
| `data.versionId` | string | Version identifier. |
| `data.tags` | string[] | Version tags after the operation. |

## Response example

`HTTP 200`:

```json
{
  "success": true,
  "data": {
    "versionId": "v3",
    "tags": ["manual"]
  }
}
```

## Error response example

404 — there is no version with that identifier:

```json
{
  "success": false,
  "error": {
    "code": "VERSION_NOT_FOUND",
    "message": "Version v3 not found"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `INVALID_TAG` | The tag is not one of `manual`, `published`. |
| 400 | `INVALID_ACTION` | The action is neither `add` nor `remove`. |
| 400 | `INVALID_VERSION_ID` | The `versionId` format does not match `v<non-negative integer>`. |
| 403 | `SOURCE_APP_ID_MISMATCH` | The call was made with an authorization key `vibe_app_…` issued for a different application. Such a key can access only its own application's snapshots, even when both applications were created by the same author. |
| 403 | `NOT_AUTHORIZED` | Only the application author, the application OAuth key, or a Bitrix24 account administrator can manage snapshots. |
| 403 | `INFRA_FORBIDDEN_FOR_COWORK_KEY` | The call was made with a Cowork key — such a key works with data only and cannot perform write operations. To issue a key that can, see [Project key for deploy](/docs/cowork/deploy-key). |
| 404 | `APP_NOT_FOUND` | The application does not exist, was deleted, or belongs to another portal. |
| 404 | `VERSION_NOT_FOUND` | A version with this `versionId` does not exist or was deleted. |

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

## See also

- [Source code storage](/docs/source-storage)
- [List versions](/docs/source-storage/versions)
- [Update version metadata](/docs/source-storage/metadata-update)
- [Deleting versions](/docs/source-storage/delete)
- [Version lifetime and cleanup](/docs/source-storage/retention)
- [Save a snapshot](/docs/source-storage/save)
