## File version history

`GET /v1/files/:id/versions`

Returns the version history of a file on Bitrix24 Drive, newest versions first. Any version from the list can be read, downloaded, or restored by its ID.

## Parameters

| Parameter | Type | Required | Default | Description |
|----------|-----|:-----:|-----------|----------|
| `id` (path) | number | yes | — | File ID. Get it: `GET /v1/files?folderId=X` |
| `limit` (query) | number | no | `50` | Number of versions to return, from 1 to 50 |
| `offset` (query) | number | no | `0` | Number of versions to skip from the start of the history |
| `filter` (query) | object | no | — | Filtering by the `id`, `size`, `name`, `createdAt`, `createdBy` fields.<br>[Filtering syntax](/docs/filtering). Example: `?filter[size][$gte]=1024` |

Pagination: one call returns at most 50 versions. To get the next page, repeat the request with `offset` set to `meta.nextOffset` from the previous response. When `meta.hasMore` is `false`, the whole history has been read.

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/files/205/versions?limit=10" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/files/205/versions?limit=10" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/files/205/versions?limit=10', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { data, meta } = await res.json()
for (const version of data) {
  console.log(version.id, version.createdAt, version.size, 'bytes')
}
console.log('More versions available:', meta.hasMore)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/files/205/versions?limit=10', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { data, meta } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success |
| `data` | array | File versions, newest first |
| `data[].id` | number | Version ID. Used by [`GET /v1/files/:id/versions/:versionId`](./version.md) |
| `data[].fileId` | number | ID of the file the version belongs to |
| `data[].size` | number | Size of the version content in bytes |
| `data[].name` | string | File name at the moment the version entered the history. Renaming the file does not change it |
| `data[].contentGeneration` | number | The file's `globalContentVersion` value at the moment the version was saved |
| `data[].createdAt` | datetime\|null | Date and time the version was saved (ISO 8601) |
| `data[].createdBy` | number | ID of the version author. List: `GET /v1/users` |
| `data[].downloadUrl` | string | Version download path without the domain — [`GET /v1/files/:id/versions/:versionId/download`](./version-download.md). Send the `X-Api-Key` header when you follow it |
| `meta.total` | number\|null | Number of versions in the history that match the request |
| `meta.limit` | number | Page size from the request |
| `meta.offset` | number | Offset from the request |
| `meta.hasMore` | boolean | Whether there are versions beyond this page |
| `meta.nextOffset` | number\|null | `offset` for the next page. `null` means there is no next page |

## Response example

```json
{
  "success": true,
  "data": [
    {
      "id": 412,
      "fileId": 205,
      "size": 10,
      "name": "report.txt",
      "contentGeneration": 4,
      "createdAt": "2026-10-15T17:11:25.000Z",
      "createdBy": 1,
      "downloadUrl": "/v1/files/205/versions/412/download"
    },
    {
      "id": 410,
      "fileId": 205,
      "size": 10,
      "name": "report.txt",
      "contentGeneration": 3,
      "createdAt": "2026-10-15T17:10:00.000Z",
      "createdBy": 1,
      "downloadUrl": "/v1/files/205/versions/410/download"
    }
  ],
  "meta": {
    "total": 2,
    "limit": 10,
    "offset": 0,
    "hasMore": false,
    "nextOffset": null
  }
}
```

## Error response example

400 — a filter on a field outside the list:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "Use limit 1..50, a non-negative offset and an object filter over id, size, name, createdAt or createdBy."
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `INVALID_PARAMS` | `limit` is outside the 1–50 range, `offset` is below zero, the filter uses a field outside the list, or `filter` is not passed as an object |
| 400 | `INVALID_PARAMS` | The filter condition key could not be parsed: the `=` sign inside the brackets is not encoded. Send the `filter[>=size]` key as `filter%5B%3E%3Dsize%5D` |
| 400 | `INVALID_ID` | `id` is not a positive integer |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `TOKEN_MISSING` | Bitrix24 access tokens are unavailable |
| 403 | `SCOPE_DENIED` | The key lacks the `disk` scope |
| 403 | `DISK_HISTORY_UNAVAILABLE` | Version history is not available on the Bitrix24 account plan |
| 404 | `ENTITY_NOT_FOUND` | No file with this `id` exists, or the key cannot access it |
| 422 | `DISK_VERSION_REFUSED` | Bitrix24 did not return the file history |
| 502 | `DISK_READ_UNAVAILABLE` | Bitrix24 returned versions of a different file in the history; the response was discarded |

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

## Known specifics

- **The first version appears when the file is created.** A freshly uploaded file already has one version in its history, holding the original content.
- **An upload does not always add a version.** If the same user changed the file less than five minutes ago, the new content overwrites the latest version: its `id` stays the same, while `size`, `contentGeneration`, and `createdAt` are updated. The previous content of that version is lost from the history, so there can be fewer versions than uploads. Details — [`POST /v1/files/:id/versions`](./version-upload.md).
- **Versions are ordered by `createdAt` with one-second precision.** Versions saved within the same second may not appear in the order they were saved. `contentGeneration` gives the exact order: a version saved later has a higher value.
- **History is limited.** How many versions are kept and for how long depends on the plan and settings of the Bitrix24 account. When a new version exceeds the limit, the oldest version is removed from the history.

## See also

- [Read a file version](/docs/entities/files/version)
- [Download a file version](/docs/entities/files/version-download)
- [Restore content from a version](/docs/entities/files/version-restore)
- [Upload a new file version](/docs/entities/files/version-upload)
- [Get file](/docs/entities/files/get)
- [Files](/docs/entities/files)
