# GET /api/v2/drive-items/{drive_item}/files

List a drive item's files

- MCP id: drive-items.files.index
- Scope: api:read:project_drive
- Scope: api:read:customer_drive
- Scope: api:read:organization_drive
- Scope: api:read:user_drive
- Permission: project_drive::access
- Rate cost: 1 unit, read bucket. `view=detail` makes it 3. Adds: each include +1, `q` +2.
- Cache-Control: private, no-store

Returns the files on one drive item, newest upload first, keyset-paginated: all three of its file collections (`attachments`, `content` for images pasted into the editor, and `file` for the single uploaded payload), so narrow with `filter[collection]=file` to get the payload alone.

There is no organisation-wide collection of files, so this nested path is the only way to list them and `filter[model_type]` / `filter[model_id]` do not exist: the parent is the path segment. Access to the parent is decided per item (the permission for the owner type, the access inherited from its folder, then any per-item grant), and an archived drive item answers `404`. The declared permission is `project_drive::access`; `customer_drive`, `organization_drive` and `user_drive` apply by owner type, and a token covering any of the four is accepted. Listing additionally requires `project_management::manage_work_items` for the files themselves. The API never streams bytes: pass `include=url` for a signed download URL per file, and attach a new file with the two-step upload flow that starts at `POST drive-items/{drive_item}/uploads`.

## Parameters
- drive_item (integer, path): The DriveItem's numeric id. Accepts a soft-deleted record.
- view (string, optional): Which field set to render.
- per_page (integer 1 to 100, optional): Rows per page. At most 25 when `include` names a to-many relation; a larger value is 400 invalid-query-parameter.
- cursor (string, optional): Opaque keyset cursor from a previous page's links.next. Never construct one by hand.
- page (integer 1 to 1000, optional): Opt in to page-number paging: 1-based, at most 1000. Omit it, the default, to page by opaque cursor, which is what links.next hands you. Cannot be combined with cursor. Published only on collections that count their rows on every request.
- filter[collection] (string, optional): Narrow to one media collection. A work item registers only `attachments`; a drive item registers `attachments`, `content` (inline editor images) and `file` (the single uploaded payload), so `filter[collection]=file` is how a client asks a drive item for its payload alone.
- filter[created_at] (timestamp (YYYY-MM-DDThh:mm:ssZ), optional): Creation timestamp. Pair with `sort=id` for a stable full export. Operators: = gte lt.
- filter[updated_at] (timestamp (YYYY-MM-DDThh:mm:ssZ), optional): Last-write timestamp. Use for incremental sync. Operators: = gte lt.
- filter[collection][starts] (string, optional): Narrow to one media collection. A work item registers only `attachments`; a drive item registers `attachments`, `content` (inline editor images) and `file` (the single uploaded payload), so `filter[collection]=file` is how a client asks a drive item for its payload alone. One value, matched literally as a prefix: send commas and backslashes as they are, and `%` and `_` match themselves rather than acting as wildcards.
- q (string, optional): Free-text search over `name`. At most one substring match per request: `q` together with a `contains` filter is 400 invalid-query-parameter.
- sort (string, optional): Up to three keys, comma-separated, each optionally prefixed with `-` for descending.
- include (string, optional): Comma-separated names to inline, at most five.
- trashed (string, optional): Whether soft-deleted rows are included.
- X-Request-Id (header, optional): A correlation id of your own. It is recorded in our logs next to the server's request id but never returned: the response header always carries the server's id. A value that does not match the pattern is discarded silently, never rejected.
- If-None-Match (header, optional): The ETag a read is conditional on. A match is answered 304 with no body.

## Response 200
- id (integer, required): Unique identifier.
- name (string ≤ 255, required): File name as uploaded.
- mime_type (string or null ≤ 255, required): IANA media type.
- size (integer, required): Size in bytes.
- disk (string ≤ 255, required): Name of the storage location the file is kept in.
- collection (string ≤ 255, required): Media collection the file belongs to.
- created_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): Upload timestamp.
- updated_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): Last-write timestamp; use for incremental sync.
- url (string or null, optional, on request): Signed download URL, requiring your bearer token. Request with `?include=url`. Null only where your organisation's file storage cannot sign URLs, in which case the response carries a `signed_url_unavailable` warning and downloads are not available through the API.
- url_expires_at (timestamp (YYYY-MM-DDThh:mm:ssZ) or null, optional, on request): When `url` stops working. Always `null` in v2.0: the signed route the URL points at does not expire. Declared so a future bounded-TTL download path is an additive change.

## Errors
- 403 forbidden-by-policy | insufficient-permission | insufficient-token-scope: Forbidden.
- 304 : Not modified.
- 400 idempotency-key-required | invalid-cursor | invalid-query-parameter | malformed-request | unsupported-parameter: Bad request.
- 401 token-expired | unauthenticated: Unauthenticated.
- 404 endpoint-not-found | resource-not-found: Not found.
- 406 not-acceptable: Not acceptable.
- 429 rate-limit-exceeded: Too many requests.
- 500 internal-error: Server error.
- 503 tenant-unavailable: Service unavailable.

## Example
```bash
curl -G \
  'https://<your-url>/api/v2/drive-items/1/files' \
  --data-urlencode 'filter[collection]=file' \
  --data-urlencode 'include=url' \
  --data-urlencode 'per_page=25' \
  -H 'Authorization: Bearer <token>' \
  -H 'Accept: application/json'
```
