## List versions

`GET /v1/apps/:id/sources`

Returns the history of saved source-code versions of the application and its linked server versions.

The operation stays available even when source saving is disabled: the previously saved history remains readable.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|----------|
| `id` (path) | UUID | yes | Application identifier. Get it via [`GET /v1/apps`](/docs/apps/list). |
| `sha256` (query) | string | no | A probe for whether an archive with the given contents already exists: exactly 64 hexadecimal characters, case-insensitive, otherwise `400 INVALID_SHA256`. The response has the same shape as without the parameter but contains only versions with this hash: if the archive is found, `versions` holds one or more entries (the same contents may have been saved both to the application and to its server), and `currentVersionId`, `totalVersions`, and `totalSizeBytes` are computed over them only. If not, `versions` is an empty array and `totalVersions` is `0`. The `linkedServerSources` section is not computed in this case, so the probe stays lightweight: the array is empty, `linkedServerSourcesTruncated` is `false`, and there is no `linkedServerHint` field. |

## Examples

### curl — personal key

```bash
curl -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/apps/<APP_ID>/sources
```

### curl — OAuth application

```bash
curl -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  https://vibecode.bitrix24.com/v1/apps/<APP_ID>/sources
```

### JavaScript — personal key

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/apps/${appId}/sources`,
  { headers: { 'X-Api-Key': 'YOUR_API_KEY' } },
)
const { data } = await res.json()
console.log(`Versions: ${data.totalVersions}, latest: ${data.currentVersionId}`)
```

### JavaScript — OAuth application

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/apps/${appId}/sources`,
  {
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  },
)
const { data } = await res.json()
console.log(`Versions: ${data.totalVersions}, latest: ${data.currentVersionId}`)
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success. |
| `data.totalVersions` | number | Total number of non-deleted versions. Counted without a cap, so with a long history it exceeds the length of the `versions` array. |
| `data.currentVersionId` | string \| null | Identifier of the most recent version (`v<N>`). `null` if there are no versions. |
| `data.totalSizeBytes` | number | Total size of all archives in bytes. |
| `data.versions` | array | The list of versions, newest first. Deleted versions are not included. **At most 500 entries** are returned — with a longer history the array is truncated. |
| `data.versions[].versionId` | string | Version identifier of the form `v<N>`. |
| `data.versions[].filename` | string | Filename in storage. Contains a `-published` or `-manual` suffix based on the version's current tags; with both tags, `-published`. |
| `data.versions[].contentType` | string \| null | The type the archive was saved with: `application/gzip`, `application/x-tar`, `application/zip`, or `application/octet-stream`. `null` for early versions whose type was not recorded. |
| `data.versions[].timestamp` | string | Save time (ISO 8601, UTC). |
| `data.versions[].size` | number | Archive size in bytes. |
| `data.versions[].sha256` | string | SHA-256 of the archive contents. Used for deduplication within one owner. |
| `data.versions[].tags` | string[] | Version tags. `manual` and `published` protect the version from automatic cleanup; any other tags are free-form labels from the `X-Tags` header at [save](/docs/source-storage/save) time or from [`PATCH`](/docs/source-storage/metadata-update). |
| `data.versions[].savedBy.userId` | string \| null | Vibecode user identifier. |
| `data.versions[].savedBy.session` | string \| null | AI session identifier from the `X-AI-Session-Id` header. |
| `data.versions[].linkedDeployId` | string \| null | Marker of the latest event involving the version. `deploy:…` — the version was saved or confirmed by a deploy. `publish:<time>` — the version was published via [`POST /v1/apps/:id/publish`](/docs/apps/publish). Publishing overwrites the deploy marker. `null` — the version has had neither a deploy nor a publication. |
| `data.versions[].deployStatus` | string \| null | How the latest deploy of this version ended: `success` or `failed`. `null` if the version has never been deployed — for example, if it was saved manually and never passed to a deploy as [`source.versionId`](/docs/infra/deploy/deploy). Publishing does not change this field, but on some older published versions `success` was set by the publication, not by a deploy. |
| `data.versions[].note` | string \| null | Note from the `X-Note` header at [save](/docs/source-storage/save) time or from [`PATCH`](/docs/source-storage/metadata-update). For a version saved by a deploy, it holds the deploy's `changelog` field or, without one, the service string `Auto-saved on deploy …` with the same deploy marker as in `linkedDeployId`. |
| `data.versions[].serverContext` | object \| null | The server managed by this application's key (`vibe_app_*`), if the version is linked to one. Server data is current as of the request. `null` if the version is not linked to a server. |
| `data.versions[].serverContext.serverId` | string | Server identifier. Get it via [`GET /v1/infra/servers`](/docs/infra/servers/list). |
| `data.versions[].serverContext.serverName` | string | System name of the server. |
| `data.versions[].serverContext.serverDisplayName` | string | Display name of the server. An empty string if the server has none. |
| `data.versions[].serverContext.linkedApp` | object \| null | The application the server's managing key is issued for. `null` if the server is managed by a personal key. |
| `data.versions[].serverContext.linkedApp.appId` | string | Application identifier. Get it via [`GET /v1/apps`](/docs/apps/list). |
| `data.versions[].serverContext.linkedApp.title` | string | Application title. |

## Linked server versions

The `versions` array lists app-scoped versions. These include versions of a server managed by this application's key (`vibe_app_*`): their `serverContext` is filled in. Versions of servers on a personal key (stored via [`POST /v1/infra/servers/:id/sources`](/docs/source-storage/servers) or by auto-save on deploy) are not included in `versions` — they are returned in a separate field `data.linkedServerSources`, grouped by server. The Response example below shows a populated section.

| Field | Type | Description |
|------|-----|----------|
| `data.linkedServerSources[]` | array | Groups of server versions, one per server. Always present. Empty if there are no linked server versions or the section was not computed; the cases are listed below the table. |
| `data.linkedServerSources[].serverContext` | object | The group's server. Same fields as `data.versions[].serverContext`. |
| `data.linkedServerSources[].totalVersions` | number | Exact number of versions on the server, not limited by the list size below. |
| `data.linkedServerSources[].totalSizeBytes` | number | Total size of that server's versions. |
| `data.linkedServerSources[].versions[]` | array | Server versions in the same shape as `versions[]`, but without the `serverContext` field: it sits on the group. The version number here comes from the server's history: it may match the number of a different version in `versions`, and the server's sequence might not start at `v1` and may contain gaps. |
| `data.linkedServerSourcesTruncated` | boolean | Always present. `true` means the section is incomplete: there are more than 50 servers with versions or more than 200 of their versions in total. `true` also comes back when the section could not be built, in which case the array is empty. The full list is available per server via [`GET /v1/infra/servers/:serverId/sources`](/docs/source-storage/servers). |
| `data.linkedServerHint` | object | Present only when `linkedServerSources` is non-empty; otherwise, the field is absent from the response. Points to the authoritative list and download endpoints for server versions. |
| `data.linkedServerHint.message` | string | Explains where the server versions are stored and where to get them. The text is in English. |
| `data.linkedServerHint.listEndpoint` | string | Endpoint template for listing a server's versions. |
| `data.linkedServerHint.downloadEndpoint` | string | Endpoint template for downloading a server version. |
| `data.linkedServerHint.docs` | string | Link to the markdown page of the Source code storage section. |

`linkedServerSources` is populated on a request without `?sha256=` when the caller is the app author (personal `vibe_api_*` key) or a Bitrix24 account administrator. In this section, the author sees only the servers of the requesting key and the server bound to that key's application. Servers created with the author's other personal keys do not appear in the section, even when the author is a Bitrix24 account administrator: a request for their sources with this key gets `404 SERVER_NOT_FOUND`. When the call uses an **OAuth application key**, the section is empty: a machine key does not enumerate the author's personal servers. Downloads and the full per-server list are available via [`GET /v1/infra/servers/:serverId/sources`](/docs/source-storage/servers), using the identifier from `serverContext.serverId`.

## Response example

`HTTP 200`:

```json
{
  "success": true,
  "data": {
    "totalVersions": 2,
    "currentVersionId": "v2",
    "totalSizeBytes": 49678,
    "versions": [
      {
        "versionId": "v2",
        "filename": "2026-08-04T10-36-36-711Z-v2.tar.gz",
        "contentType": "application/gzip",
        "timestamp": "2026-08-04T10:36:36.711Z",
        "size": 174,
        "sha256": "1b8d9dcdb0960d4cea381ae1f80bfaab4af3a27ec9645136242575ac35f9da3b",
        "tags": [],
        "savedBy": {
          "userId": "48bdfd33-5fbe-4ad1-a02c-9b5c7ae65f77",
          "session": null
        },
        "linkedDeployId": null,
        "deployStatus": null,
        "note": "Fixed the sign-in form",
        "serverContext": null
      },
      {
        "versionId": "v1",
        "filename": "2026-08-04T10-01-25-947Z-v1.tar.gz",
        "contentType": "application/gzip",
        "timestamp": "2026-08-04T10:01:25.947Z",
        "size": 49504,
        "sha256": "e28aaf8af203804c934e6881c94472a420174f58c9442ecef82dba44c6cf989b",
        "tags": [],
        "savedBy": {
          "userId": "48bdfd33-5fbe-4ad1-a02c-9b5c7ae65f77",
          "session": null
        },
        "linkedDeployId": null,
        "deployStatus": null,
        "note": "First version",
        "serverContext": null
      }
    ],
    "linkedServerSources": [
      {
        "serverContext": {
          "serverId": "86dba796-5b36-49ef-a12e-55f1fc2229dd",
          "serverName": "shop-api",
          "serverDisplayName": "Shop: API",
          "linkedApp": null
        },
        "totalVersions": 1,
        "totalSizeBytes": 1430,
        "versions": [
          {
            "versionId": "v1",
            "filename": "2026-09-03T07-30-46-098Z-v1.tar.gz",
            "contentType": "application/gzip",
            "timestamp": "2026-09-03T07:30:46.098Z",
            "size": 1430,
            "sha256": "3ac41f26c943713b4ed4b85a8ec20a7b7d1dbdfeeee0634712251419a15a328b",
            "tags": [],
            "savedBy": {
              "userId": "48bdfd33-5fbe-4ad1-a02c-9b5c7ae65f77",
              "session": null
            },
            "linkedDeployId": "deploy:2026-09-03T07:30:44.843Z",
            "deployStatus": "success",
            "note": "Auto-saved on deploy 2026-09-03T07:30:44.843Z"
          }
        ]
      },
      {
        "serverContext": {
          "serverId": "07312566-9915-4338-bf3f-997318013237",
          "serverName": "landing",
          "serverDisplayName": "Landing",
          "linkedApp": null
        },
        "totalVersions": 1,
        "totalSizeBytes": 374,
        "versions": [
          {
            "versionId": "v1",
            "filename": "2026-08-07T11-53-13-340Z-v1.tar.gz",
            "contentType": "application/gzip",
            "timestamp": "2026-08-07T11:53:13.340Z",
            "size": 374,
            "sha256": "98021c03c7ccd84493d872e1dfcbb083686368b6df8e2b53b64a1ce8bfd72e20",
            "tags": [],
            "savedBy": {
              "userId": null,
              "session": null
            },
            "linkedDeployId": "deploy:2026-08-07T11:53:13.038Z",
            "deployStatus": "success",
            "note": "Auto-saved on deploy 2026-08-07T11:53:13.038Z"
          }
        ]
      }
    ],
    "linkedServerSourcesTruncated": false,
    "linkedServerHint": {
      "message": "This app has source versions stored under a server (server-keyed storage). List and download them via the server endpoint.",
      "listEndpoint": "GET /v1/infra/servers/:serverId/sources",
      "downloadEndpoint": "GET /v1/infra/servers/:serverId/sources/:versionId/download",
      "docs": "https://vibecode.bitrix24.com/docs-content-en/source-storage.md"
    }
  }
}
```

## Error response example

404 — there is no application with that identifier:

```json
{
  "success": false,
  "error": {
    "code": "APP_NOT_FOUND",
    "message": "Application not found"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `INVALID_SHA256` | The `sha256` parameter is not exactly 64 hexadecimal characters. |
| 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` | The personal key belongs neither to the application author nor to a Bitrix24 account administrator and was not issued for this application. |
| 404 | `APP_NOT_FOUND` | The application does not exist, was deleted, or belongs to another portal. |

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

## See also

- [Source code storage](/docs/source-storage)
- [Get version metadata](/docs/source-storage/versions-get)
- [Download the archive](/docs/source-storage/versions-download)
- [Save a snapshot](/docs/source-storage/save)
- [Version tags and notes](/docs/source-storage/metadata)
- [Server-keyed source endpoints](/docs/source-storage/servers)
- [Source registry and Bitrix24 account state](/docs/source-storage/registry)
