---
title: "List tool files you can reach"
method: GET
path: "/file"
tags: ["Files"]
---

# List tool files you can reach

`GET /file`

## Request

- Base URL: `https://api.elaichi.ai`
- URL: `https://api.elaichi.ai/file`
- Auth: HTTP bearer

Lists every file the caller can reach, newest first, never an expired one: the files they own, the files an owner shared with them by name (directly, through a team they are in, or organization-wide), and the files they reach through the source: `use` or better on the connection the file came through, or on the toolbox it ran in (the toolbox only while it still pins the file’s connection with a working delegation). A file is treated like the connection or toolbox it came out of: if you can use what made it, you see it. No permission is required beyond organization membership, and there is no admin view: an org owner sees what they own or reach, like anyone else.

**A file your organization’s restrictions block is still listed**, flagged `restricted_by` with `can_open: false`, the way a blocked connection stays in `GET /connection`. `can_open` is also `false` on a row reached through a toolbox whose delegation no longer holds or whose source connection has been deleted, and on every such row when the restriction lookup failed. The content route stays the authority.

**Cost.** An unfiltered page does work proportional to the number of connections and toolboxes the caller can use times the page size, not to the number of files. A `connector_slug` filter narrows that and stays cheap; a rare substring `q` and `created_before` can still scan much of what the caller reaches before a page fills (bounded by the 7-day retention).

A caller that already ran the tool has the id from the tool result and can skip this entirely. `?q=`, `?scope=`, `?connection_id=`, `?connector_slug=`, `?type=` and `?created_before=` are all applied before paging. Every row says how the caller reaches it (`access`, and `access_via`, which for a file may also be `connection` or `toolbox`), whether it will open (`can_open`, `restricted_by`) and what they may do to it (`can_delete`, `can_share`, `can_see_shares`, `can_revoke_share`, all owner-only). A row the caller does not own omits the owner’s provenance (`connection_id`, `toolbox_id`, `tool_name` and `delegated_by_user_id`) and `access_summary`; it keeps the file, `connector_slug`, `tool_resource` and `tool_method` (the words for “from …”), `created_by` and the caller’s own `access_via`.

## Query parameters

- `limit` integer
- `cursor` string
- `q` string
- `scope` 'owned' | 'shared'
- `connection_id` string
- `connector_slug` string
- `type` string
- `created_before` string, date-time

## Headers

- `X-Organization-Id` string

## Response `200`

OK. Beside the usual envelope: `can_upload` (whether uploads are available) and `upload_limits` (the limits every upload shows), repeated on every page.

- object
  - `result` object[], required
    - `id` string: File id (`file_…`).
    - `organization_id` string
    - `created_by_user_id` string: The member who ran the tool: the file’s owner. Not the owner of the connection behind it.
    - `filename` string
    - `mime` string
    - `size_bytes` integer
    - `connection_id` string, nullable: Provenance, and one source of access: a member with `use` or better on this connection sees the file in `GET /file` and can open it. It is never the owner’s gate: a `use` grantee can own a file made over a connection they cannot see at all. **Present only on rows the caller owns** — omitted, not null, on a file shared with them.
    - `toolbox_id` string, nullable: Provenance, and a second source of access: `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, nullable: 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, nullable: 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.
    - `tool_method` string, nullable: Catalog method of the tool that produced the file (e.g. `export`), safe to show a person. Set on every file.
    - `delegated_by_user_id` string, nullable: 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, date-time
    - `origin` 'tool' | 'upload' | 'request' | 'inline' | 'api' | 'url_import' | 'web_fetch' | 'export': 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.
    - `origin_host` string, nullable: The web host an import or web fetch read from, or the asking app’s name for origin `request`; null otherwise.
    - `expires_at` string, date-time: Defaults to 7 days after creation. Enforced when the file is read: past this instant the file is absent from `GET /file` and answers `404` on the content route, for the owner and every grantee alike. The stored file is deleted shortly afterwards.
    - `access` 'owner' | 'view': 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.
    - `access_via` 'owner' | 'direct' | 'team' | 'org' | 'connection' | 'toolbox': How the caller reaches this file, not who else can. `owner`: they own it. `direct`: a grant names them personally. `team`: a grant to a team they belong to (or administer), named in `access_via_team`. `org`: an organization-wide grant. When several sources apply, the broadest wins and the access level plays no part: owner, else `org`, else `team`, else `direct`. A caller with `edit` personally and `view` org-wide reads `org`, because this field says how far the file reaches, not what the caller may do with it. It describes only the caller's own access, so a `view` or `use` grantee still gets it while the list of other grantees stays hidden. Absent when nothing reaches the caller (for example, the former owner after a transfer of a resource that was never shared); absent never means `org`. A file adds two values for access nobody granted by name: `connection` (the caller has `use` or better on the connection the file came through) and `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` or `org`) outranks both when it also applies, and `toolbox` outranks `connection` when a file is reached both ways. Only file rows carry `connection` and `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, nullable: 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. `name` is null for someone who has left the organization.
      - `id` string: User id (`usr_…`) — same value as `created_by_user_id`.
      - `name` string, nullable
    - `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 a row reached through its source connection or toolbox it is `false` when an org restriction blocks the connector or the tool (`restricted_by` is then set), when the toolbox’s delegation no longer holds (its pinning entry’s delegator lost `use`), or when the source connection has been deleted; in the last two cases `restricted_by` is null. If the restriction lookup itself fails, such rows read `false` too. This is a prediction for the page, not a second gate: `GET /file/{id}/content` stays the authority and answers a uniform `404` for anything this says `false` to.
    - `restricted_by` 'role' | 'user' | 'null', nullable: 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: it adds which layer to `can_open`’s whether, and no rule id, author or reason. Non-null only on rows reached through a source connection or toolbox (`access_via` is `connection` or `toolbox`), because a restriction applies to that route alone: an owned or explicitly shared row is always null, and so is a row that will not open for any other reason (a lapsed toolbox delegation, a deleted connection). The row is listed and flagged, never omitted, so a page can hold rows the caller cannot open.
    - `access_summary` object: The file’s audience as a short summary. Present on rows the caller owns only, never on a file shared with them (the 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` 'view' | 'use' | 'edit' | 'null', nullable: Level of the org-wide grant, or null when there is none.
      - `team_count` integer
      - `user_count` integer
      - `total` integer: Every grant, the org-wide one included.
      - `preview` object[]: At most 5 grantees, broadest first (org, then teams, then members), for a hover preview.
        - `grantee_type` 'user' | 'team' | 'org'
        - `grantee_id` string, nullable
        - `level` 'view' | 'use' | 'edit'
        - `name` string, nullable: Display name; null for org grants and for grantees no longer in the org.
    - `kind` 'document' | 'spreadsheet' | 'presentation' | 'image' | 'archive' | 'other': Coarse bucket derived from the stored `mime` by the same classification `?type=` filters with. `other` is everything the named kinds do not claim.
    - `connector_slug` string, nullable: 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, nullable: `connector_slug`’s display data, the same as on a `GET /connection` row. Null exactly when `connector_slug` is; a connector the catalog cannot resolve reads its slug as `label` and a null `logo`.
      - `label` string, required
      - `logo` string, nullable, required
      - `upstream_slug` string: Only on a fork whose upstream the caller may see, by the same rule as `GET /connector`.
  - `next_cursor` string, nullable, required
  - `prev_cursor` string, nullable, required
  - `can_upload` boolean, required
  - `upload_limits` object, required
    - `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` string[], nullable: Allowed media types (`image/*`, `application/pdf`) and extensions (`.csv`); null means anything.

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `429`: Rate limited

---

[API](https://skmtc.dev/elaichi/apis/elaichi-api.md) · [All operations](https://skmtc.dev/elaichi/apis/elaichi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/elaichi/apis/elaichi-api/revisions/b22cfb7b6d15?raw)
