# Agent API (/docs/api/agent)

The agent API does what agents need from the library: browse and search files, change their details, add files from a URL, sort them into folders and share them. The [MCP server](/docs/agents) runs on it, and [`/openapi.json`](https://media.obelism.studio/openapi.json) describes it.

## Signing in [#signing-in]

Every request carries a session token from www.obelism.studio as the bearer, the same token Content's agent API takes:

```http
POST https://www.obelism.studio/api/agent/auth/sign-in
Content-Type: application/json

{ "email": "…", "password": "…" }
```

It answers a `token`. An account with two-factor authentication also sends `code`, the current code from the authenticator app. Then:

```
Authorization: Bearer <token>
```

You act as yourself: reads take any role in the Space, changes take an admin, developer or editor role. Agents connected through MCP use OAuth instead and need no token.

## Operations [#operations]

Every path below starts with `/api/agent`. `{org}` and `{space}` are the ids from `listOrganizations` and `listSpaces`.

| Operation           | Request                                          |
| ------------------- | ------------------------------------------------ |
| `listOrganizations` | `GET /organizations`                             |
| `listSpaces`        | `GET /organizations/{org}/spaces`                |
| `listFiles`         | `GET /organizations/{org}/spaces/{space}/files`  |
| `uploadFile`        | `POST /organizations/{org}/spaces/{space}/files` |
| `getFile`           | `GET …/{space}/files/{assetId}`                  |
| `updateFile`        | `POST …/{space}/files/{assetId}`                 |
| `listFolders`       | `GET …/{space}/folders`                          |
| `createFolder`      | `POST …/{space}/folders`                         |
| `changeFolder`      | `POST …/{space}/folders/{folderId}`              |
| `deleteFolder`      | `POST …/{space}/folders/{folderId}/delete`       |
| `moveFiles`         | `POST …/{space}/move-files`                      |
| `listShares`        | `GET …/{space}/shares`                           |
| `createShare`       | `POST …/{space}/shares`                          |
| `listUploadRules`   | `GET …/{space}/rules`                            |

Send and expect JSON.

### Files [#files]

- **`listFiles`** lists files newest first, 48 at a time (`limit`, 100 at most; `skip` to page), with `total`. `folderId` keeps to one folder (empty for the root); `query` (part of the file name), `tag` and `product` (a Shopify product GID, `gid://shopify/Product/…`) search every folder.
- **`getFile`** answers one file with its details, `usages` (where Content uses it) and `originalUrl`: the [raw file](/docs/files/raw-files) behind a link that lasts 15 minutes.
- **`updateFile`** changes `title` and `alt` (`{ "en": "…" }`, per language), `focalPoint` (`{ x, y }`, each 0 to 1, or `null`), `tags` (the whole list) and `folderId` (`null` for the root). Leave out what stays.
- **`uploadFile`** fetches a file from an `https` URL (`url`, 50 MB at most, of the type it claims), into `folderId` or where the [upload rules](/docs/library/rules) put it, with optional `title`, `alt` and `tags`.

A file's `url` is its optimized URL on Content, the one sites use.

```bash
curl https://media.obelism.studio/api/agent/organizations/$ORG/spaces/$SPACE/files/$FILE \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "alt": { "en": "Two people on a beach at sunset" }, "focalPoint": { "x": 0.4, "y": 0.6 } }'
```

### Folders [#folders]

- **`listFolders`** answers every folder with its `parentId` and how many files it holds, and `rootFiles`.
- **`createFolder`** takes `name` and an optional `parentId`.
- **`changeFolder`** renames (`name`) and moves (`parentId`, `null` for the root) a folder, either or both.
- **`deleteFolder`** deletes an empty folder; one that still holds folders or files answers `409`.
- **`moveFiles`** moves `assetIds` (up to 500) into `folderId` (`null` for the root). No URL changes.

### Shares and rules [#shares-and-rules]

- **`createShare`** shares `assetIds` (up to 100) or a `folderId`, from `startsAt` (now) to `endsAt` (a week; a month at most), with a `password` of at least 8 characters, made up when left out. It answers the link and the password, which is never readable again. See [shares](/docs/library/shares).
- **`listShares`** lists the Space's shares with their window and openings; `assetId` keeps to the shares holding that file.
- **`listUploadRules`** answers the Space's [upload rules](/docs/library/rules), in order.

## Limits and errors [#limits-and-errors]

300 calls a minute per person, across the API and the MCP server. Errors are problem JSON with a `code` and a `hint` ([errors](/docs/api/errors)).

What the agent API doesn't do: replacing, deleting or making files private, uploading from your computer, and ending shares. Use the library for those.
