# List tool files you can reach

> Source: https://elaichi.ai/docs/api-reference/files/file/listfiles/

`GET /file`

Resource: **File** · API: **Files**

## Query parameters

- **`q`** _(string)_
  Case-insensitive substring match on the file’s filename. LIKE wildcards are matched literally. Max 200 characters.
- **`scope`** _(string)_
  `owned` — only files the caller ran the tool for. `shared` — every visible file the caller did NOT make: explicitly shared with them AND reached through a source connection or toolbox. Absent — both.
  Allowed: `owned`, `shared`
- **`connection_id`** _(string)_
  Only the caller’s OWN files produced through this connection. A row the caller does not own does not disclose its `connection_id`, so this filter never matches one.
- **`connector_slug`** _(string)_
  Only files produced through a connection of one of these connectors. Comma-separated or repeated, at most 25 (more is a `400`). Files with no surviving connection never match.
- **`type`** _(string)_
  Only files of these kinds (the row’s `kind`). Comma-separated, any of `document`, `spreadsheet`, `presentation`, `image`, `archive`, `other` (anything else is a `400`).
- **`created_before`** _(string)_
  Only files created strictly before this ISO-8601 timestamp.

## Response body

- **`result`** _(array<object>)_
  - **`id`** _(string)_
    File id (`file_…`).
  - **`organization_id`** _(string)_
  - **`created_by_user_id`** _(string)_
    The member who RAN the tool — the file’s owner, and the first of its three access tiers (see `GET /file/{id}/content`). Not the owner of the connection behind it.
  - **`filename`** _(string)_
  - **`mime`** _(string)_
  - **`size_bytes`** _(integer)_
  - **`connection_id`** _(string,null)_
    Provenance, and the source of the inherited reach: a member with `use` or better on this connection sees the file in `GET /file` and can open it. Never the owner’s gate — a `use` grantee can own a file made over a connection they cannot see at all (delegation is disclosed, not gated). **Present only on rows the caller owns** — omitted, not null, on a file shared with them.
  - **`toolbox_id`** _(string,null)_
    Provenance, and the second source of inherited reach: `use` or better on this toolbox lists and opens the file (while the toolbox still pins the file’s connection). **Present only on rows the caller owns** — omitted, not null, on a file shared with them.
  - **`tool_name`** _(string,null)_
    The model-facing tool name; can be an opaque `tb__…` string. Never show it to a person — word `tool_resource` and `tool_method` instead. **Present only on rows the caller owns** — omitted, not null, on a file shared with them.
  - **`tool_resource`** _(string,null)_
    Catalog resource of the tool that produced the file (e.g. `slides`), safe to show a person. Set on every file, because only a connected tool can produce one (a synthetic tool never does); typed nullable in the schema only; no code path writes a null.
  - **`tool_method`** _(string,null)_
    Catalog method of the tool that produced the file (e.g. `export`), safe to show a person. Set on every file; typed nullable in the schema only, like `tool_resource`.
  - **`delegated_by_user_id`** _(string,null)_
    Set when the tool ran over a connection delegated to the creator; null when they used their own. **Present only on rows the caller owns** — omitted, not null, on a file shared with them.
  - **`created_at`** _(string)_
  - **`origin`** _(string)_
    How the bytes got here: `tool` (a connector tool returned them), `upload` (a person chose it on the Files screen), `request` (a person handed it to an app that asked, through an upload request; `origin_host` is the app), `inline` (content an assistant wrote with `file.create`), `api` (a backend sent it to `POST /file` with a token), `url_import`, `web_fetch` (fetched from the web), `export` (produced by an export). Provenance for wording (“Uploaded by Dana”), never an access gate.
    Allowed: `tool`, `upload`, `request`, `inline`, `api`, `url_import`, `web_fetch`, `export`
  - **`origin_host`** _(string,null)_
    The web host an import or web fetch read from, or the asking app’s name for origin `request`; null otherwise.
  - **`expires_at`** _(string)_
    Defaults to 7 days after creation. Enforced at read time: past this instant the file is absent from `GET /file` and answers `404` on the content route, for the owner and every grantee alike. A daily sweep then deletes the R2 object and this row.
  - **`access`** _(string)_
    The caller’s own reach: `owner` for a file they ran the tool for, `view` for one an owner shared with them or one they reach through its source connection or toolbox.
    Allowed: `owner`, `view`
  - **`access_via`** _(string)_
    How the CALLER reaches this file — not who else can. `owner` — they own it. `direct` — a grant naming them personally. `team` — a grant to a team they belong to (or, per §6.2, one they administer), named in `access_via_team`. `org` — an organization-wide grant. When several sources apply the BROADEST wins and the caller's access level is not consulted: owner, else `org`, else `team`, else `direct`. So a caller granted `edit` personally AND `view` org-wide reads `org` — a narrower grant must never mask org-wide exposure, since this field says how far the file reaches, not what the caller may do with it. Deliberately NOT gated on `can_see_shares`, and deliberately not a widening of it: this is the caller's OWN grant and their OWN team memberships, so a `view`/`use` grantee receives it while the grantee list — information about colleagues — stays closed to them. No other member is ever named. ABSENT when nothing reaches the caller — a transfer answering the ex-owner of a resource that was never shared, or a catalog row browsed with no grant behind it. Absent means "no source to name", never "not permitted", and never an implied `org`. A file adds two values for reach nobody granted by name (tier 3, docs/access-model.md §15): `connection` — the caller has `use` or better on the connection the file came through; `toolbox` — they have `use` or better on the toolbox it ran in (and that toolbox still pins the file’s connection). A named grant (`direct` / `team` / `org`) outranks both when it also applies, and `toolbox` outranks `connection` when a file is reached both ways. Only file rows carry `connection` / `toolbox`.
    Allowed: `owner`, `direct`, `team`, `org`, `connection`, `toolbox`
  - **`access_via_team`** _(object)_
    Present exactly when `access_via` is `team`, absent otherwise. The team the caller reaches this file through — one of their own teams, never a disclosure about anybody else.
    - **`id`** _(string)_
      Team id (`team_…`).
    - **`name`** _(string,null)_
      Team display name, or null when the team no longer resolves in the directory — the same null contract every resolved grantee name carries.
  - **`created_by`** _(object)_
    Who ran the tool, resolved in one batch for the page. `name` is null for someone who has left the organization.
    - **`id`** _(string)_
      User id (`usr_…`) — same value as `created_by_user_id`.
    - **`name`** _(string,null)_
  - **`can_delete`** _(boolean)_
    Whether the caller may `DELETE /file/{id}` — the owner, and only the owner. No permission verb to mirror.
  - **`can_share`** _(boolean)_
    Whether the caller may `POST /file/{id}/share` — the owner, and only the owner. There is no `file:share` permission; ownership is the gate.
  - **`can_see_shares`** _(boolean)_
    Whether the caller may `GET /file/{id}/share` — the owner, and only the owner. Read this rather than inferring "not permitted" from the absence of `access_summary`.
  - **`can_revoke_share`** _(boolean)_
    Whether the caller may `DELETE /file/{id}/share/{aclId}` — the owner, and only the owner. Named for the question it answers: no `file:revoke` verb exists.
  - **`can_open`** _(boolean)_
    Whether the file’s bytes will be served to the caller right now. `true` for an owned or explicitly shared row. On an inherited row it is `false` when an org restriction blocks the connector or the tool (`restricted_by` is then set), when the toolbox’s delegation chain no longer holds (its pinning entry’s delegator lost `use`), or when the source connection has been deleted (the read path fails closed) — in the last two `restricted_by` is null. If the org-restriction lookup itself errors, the list fails closed per row: every inherited row that needed a verdict reads `false` (and `restricted_by` null). A prediction made for the page, not a second gate: `GET /file/{id}/content` stays the authority and answers its uniform `404` for anything this says `false` to. Read this instead of re-deriving it.
  - **`restricted_by`** _(string,null)_
    Which precedence layer’s restriction blocks this file for the caller, null when none does. Same field and meaning as `restricted_by` on a connector or connection row — adds *which* to `can_open`’s *whether*, and no rule id, author or reason. Non-null only on **inherited** rows (`access_via` `connection` / `toolbox`): the restriction veto applies to tier 3 alone, so an owned or explicitly shared row is always null, and it is null on an inherited row that will not open for any other reason (a lapsed toolbox delegation, a deleted connection). The row is LISTED and flagged, never omitted — restrictions are evaluated per caller in the Worker, not in the list query — so a page can hold rows the caller cannot open.
    Allowed: `role`, `user`, `null`
  - **`access_summary`** _(object)_
    The file’s audience as a bounded rollup — present on rows the caller OWNS only, never on a file shared with them (that summary describes the owner’s audience, which a grantee has no business seeing). Grants are `view` only. Page `GET /file/{id}/share` for the grants themselves.
    - **`org_level`** _(string,null)_
      Level of the org-wide grant, or null when there is none.
      Allowed: `view`, `use`, `edit`, `null`
    - **`team_count`** _(integer)_
    - **`user_count`** _(integer)_
    - **`total`** _(integer)_
      Every grant, the org-wide one included.
    - **`preview`** _(array<object>)_
      At most 5 grantees, broadest first (org, then teams, then members), for a hover preview.
      - **`grantee_type`** _(string)_
        Allowed: `user`, `team`, `org`
      - **`grantee_id`** _(string,null)_
      - **`level`** _(string)_
        Allowed: `view`, `use`, `edit`
      - **`name`** _(string,null)_
        Display name; null for org grants and for grantees no longer in the org.
  - **`kind`** _(string)_
    Coarse bucket derived from the stored `mime` by the same classifier `?type=` filters with, so a row’s `kind` and the filter cannot disagree. `other` is everything the five named kinds do not claim.
    Allowed: `document`, `spreadsheet`, `presentation`, `image`, `archive`, `other`
  - **`connector_slug`** _(string,null)_
    Connector of the connection the file came through (the `?connector_slug=` filter). Null when it came through no connection or that connection has since been deleted.
  - **`connector`** _(object,null, required)_
    `connector_slug`'s display data — the same stamp a `GET /connection` row carries, resolved in one batch for the page. Null exactly when `connector_slug` is; a connector the catalog cannot resolve reads its slug as `label` and a null `logo`.
- **`next_cursor`** _(string,null)_
- **`prev_cursor`** _(string,null)_
- **`can_upload`** _(boolean)_
- **`upload_limits`** _(object)_
  - **`max_files`** _(integer)_
    Files at most. 10.
  - **`max_file_bytes`** _(integer)_
    The most one file may be. 95 MiB, or the request’s lower setting.
  - **`max_total_bytes`** _(integer)_
    The most the whole request may hold. 250 MiB.
  - **`accept`** _(array,null)_
    Allowed media types (`image/*`, `application/pdf`) and extensions (`.csv`); null means anything.

## Code examples

### curl

```bash
curl -X GET 'https://api.elaichi.ai/file' \
  -H 'Authorization: Bearer $ELAICHI_API_TOKEN' \
  -H 'Content-Type: application/json'
```

### JavaScript

```javascript
const response = await fetch('https://api.elaichi.ai/file', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer ' + process.env.ELAICHI_API_TOKEN,
    'Content-Type': 'application/json',
  },
});

const data = await response.json();
console.log(data);
```

### Python

```python
import os
import requests

url = "https://api.elaichi.ai/file"
headers = {
    "Authorization": f"Bearer {os.environ['ELAICHI_API_TOKEN']}",
    "Content-Type": "application/json",
}

response = requests.get(url, headers=headers)
print(response.json())
```
