## List upload operations

`GET /v1/disk/uploads`

Returns Bitrix24 Drive file upload operations created in the [key context](/docs/disk/uploads-reserve#known-specifics): unfinished or recently finished. Helps recover a lost operation ID and find records with an unknown outcome.

## Parameters

| Parameter | Type | Required | Default | Description |
|----------|-----|:-----:|-----------|----------|
| `filter` (query) | string | yes | — | `pending` — operations in progress: `phase` is `prepared` or `submitting`, or `application` is `unknown`. `recent` — finished operations with `application` equal to `applied` or `not_applied`, created within the last 90 days |
| `limit` (query) | number | no | `50` | Records per page, an integer from `1` to `100` |
| `cursor` (query) | string | no | — | The `nextCursor` value from the previous response. Omit it in the first request |

The request accepts no other parameters: an unknown parameter returns `400 INVALID_PARAMS`.

Records are sorted from oldest to newest. While the response has `hasMore: true`, request the next page with `cursor` set to `nextCursor` and the same `filter`.

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/disk/uploads?filter=recent&limit=2" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/disk/uploads?filter=recent&limit=2" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — personal key

```javascript
const items = []
let cursor
do {
  const params = new URLSearchParams({ filter: 'recent', limit: '2' })
  if (cursor) params.set('cursor', cursor)
  const res = await fetch(`https://vibecode.bitrix24.com/v1/disk/uploads?${params}`, {
    headers: { 'X-Api-Key': 'YOUR_API_KEY' },
  })
  const { success, data, error } = await res.json()
  if (!success) throw new Error(error.code)
  items.push(...data.items)
  cursor = data.hasMore ? data.nextCursor : undefined
} while (cursor)

console.log(items.map(item => `${item.intentSummary.effectiveFilename}: ${item.application}`))
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/disk/uploads?filter=recent&limit=2', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

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

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | `true` on a successful read |
| `data.items` | array | Operations on the page. An empty array if nothing matches `filter` |
| `data.items[].operationId` | string | Operation ID. Details: [`GET /v1/disk/uploads/:operationId`](/docs/disk/uploads-get) |
| `data.items[].phase` | string | Operation phase: `prepared`, `submitting` or `settled` |
| `data.items[].application` | string | Write outcome: `applied`, `not_applied` or `unknown` |
| `data.items[].verification` | string | Result of the last check against the current file: `matched`, `superseded` or `unavailable` |
| `data.items[].intentSummary.mode` | string | Mode from the reservation: `create` or `version` |
| `data.items[].intentSummary.targetId` | string | Folder ID for `create` or file ID for `version` |
| `data.items[].intentSummary.effectiveFilename` | string | File name from the reservation |
| `data.items[].intentSummary.contentSize` | string | File size in bytes |
| `data.items[].intentSummary.intentHash` | string | The operation's `intentHash` — required by [`POST /v1/disk/uploads`](/docs/disk/uploads) |
| `data.items[].priorOperationId` | string | The previous operation this one was reserved from. Returned for operations with `lineage.kind` equal to `successor` or `retry` |
| `data.hasMore` | boolean | `true` if there is a next page |
| `data.nextCursor` | string | Cursor of the next page. Returned when `hasMore: true` |

## Response example

First page of `filter=recent&limit=2`:

```json
{
  "success": true,
  "data": {
    "items": [
      {
        "operationId": "zSTFAm53NusAWc94THbRTOfbe-OIoHwlDIJTQ6E2Z7o",
        "phase": "settled",
        "application": "applied",
        "verification": "matched",
        "intentSummary": {
          "mode": "create",
          "targetId": "1",
          "effectiveFilename": "vibe-disk-docs-check.txt",
          "contentSize": "27",
          "intentHash": "3e55280c097b92721a6c58da586363f1169e7dec15990fe3fa7f44f543b8331a"
        }
      },
      {
        "operationId": "xykPPgOlNBiKMTlAV3SfBoGJhG6Hi6AX57Ede4rAFoU",
        "phase": "settled",
        "application": "applied",
        "verification": "superseded",
        "intentSummary": {
          "mode": "create",
          "targetId": "1",
          "effectiveFilename": "vibe-disk-docs-check-2.txt",
          "contentSize": "29",
          "intentHash": "3e10ae1152a0e4b4e89d3b312bfacafc1f3e0cf22d8a5eae3e231fa8bc274498"
        }
      }
    ],
    "hasMore": true,
    "nextCursor": "xykPPgOlNBiKMTlAV3SfBoGJhG6Hi6AX57Ede4rAFoU"
  }
}
```

The next page with `cursor` — the operation for a new file version carries `priorOperationId`:

```json
{
  "success": true,
  "data": {
    "items": [
      {
        "operationId": "dlbBsp01PqU2VBXjA8VigHPCXE_T01lBJgCp_gNfypY",
        "phase": "settled",
        "application": "applied",
        "verification": "matched",
        "intentSummary": {
          "mode": "version",
          "targetId": "10901",
          "effectiveFilename": "vibe-disk-docs-check-2.txt",
          "contentSize": "32",
          "intentHash": "07b6444b0eb202f1c7c11b50d5617a86790e80e6bb9d487c0e90776d1a0f0a75"
        },
        "priorOperationId": "xykPPgOlNBiKMTlAV3SfBoGJhG6Hi6AX57Ede4rAFoU"
      },
      {
        "operationId": "QSCV6zB59O811A1pNO9HfekQdMvGifw4_E9-y1OZs48",
        "phase": "settled",
        "application": "not_applied",
        "verification": "unavailable",
        "intentSummary": {
          "mode": "version",
          "targetId": "10901",
          "effectiveFilename": "vibe-disk-docs-check-2.txt",
          "contentSize": "16",
          "intentHash": "76d560e3bf0b2bfabb85152474db537ebb08225558e37537f9ff86fbafebe0ad"
        }
      }
    ],
    "hasMore": false
  }
}
```

## Error response example

400 — `limit` is greater than `100`:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "Disk request unavailable",
    "retrySafe": false
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `INVALID_PARAMS` | `filter` is missing or is neither `pending` nor `recent`, `limit` is not an integer from `1` to `100`, `cursor` is longer than 512 characters, or an unknown parameter is passed |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `INVALID_API_KEY` | The key is not recognized |
| 401 | `TOKEN_MISSING` | The key has no connection to Bitrix24 |
| 401 | `DISK_AUTH_UNAVAILABLE` | The Bitrix24 user could not be confirmed: an application key was passed without `Authorization: Bearer`, the session does not belong to the key's application, or the key is not supported by the Drive agent |
| 401 | `TOKEN_REFRESH_FAILED` | The portal authorization for the key could not be refreshed. A retry does not help until the key is authorized again |
| 403 | `SCOPE_DENIED` | The key lacks the `disk` scope |
| 403 | `DISK_ACCESS_DENIED` | Bitrix24 denied access while checking the user |
| 409 | `DISK_OPERATION_CONFLICT` | `cursor` is not an operation ID in the key context |
| 502 | `DISK_READ_UNAVAILABLE` | Bitrix24 returned an error that Vibecode did not recognize |
| 503 | `QUERY_LIMIT_EXCEEDED` | Bitrix24 throttled the request rate. Retry later |
| 503 | `BITRIX_TIMEOUT` | Bitrix24 did not respond in time |
| 503 | `QUEUE_OVERFLOW`, `QUEUE_TIMEOUT` | The portal call queue is full. The `Retry-After` header gives the pause before a retry |
| 503 | `RATE_LIMITED` | The portal responded with HTTP 429. The `Retry-After` header gives the pause before a retry |
| 503 | `ERROR_LOOP_DETECTED` | Repeated errors from this key on this method have temporarily stopped calls. The `Retry-After` header gives the pause |
| 503 | `user_self_deletion_pending` | The key owner requested deletion of their account — Drive calls are stopped |

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

## Known specifics

- **`verification` is not recomputed in the list.** The field carries the result of the last check. To check an operation against the current file, request [`GET /v1/disk/uploads/:operationId`](/docs/disk/uploads-get).

## See also

- [Get an upload operation](/docs/disk/uploads-get)
- [Reserve a file upload to Drive](/docs/disk/uploads-reserve)
- [Upload file content to Drive](/docs/disk/uploads)
- [Errors](/docs/errors)
