# Files.fm Cloud Storage API

Files.fm is a cloud storage platform with an HTTPS REST API (GET/POST), plus FTP/FTPS and WebDAV access. This document is the single source of truth for the Files.fm API. It merges the modern REST API V2 (recommended for new integrations) with the legacy V1 endpoints (kept for compatibility), and is intended for both human programmers and LLM/AI agents.

The content is verified against the live code: the V2 router `api/v2/index.php`, the V1 scripts under `api/`, and the shared authenticator `api/authenticate_user.php`. The REST V2 and integration sections also derive from `Files.fm_API_docs_EN_v.1.9.5.pdf` (version 1.9.5, dated 2026-05-01); legacy V1 endpoints derive from the public API reference page and the live `/api/` scripts. Concrete access tokens and hashes in examples are placeholders.

For new integrations, prefer API V2 where available. The legacy V1 endpoints remain documented because many of them have no V2 equivalent (thumbnails, recursive tree, ZIP download, versions, sharing, embedding, and more).

## REST API Overview

Base API host:

```text
https://api.files.fm
```

Web links and the file browser use the base web host `https://files.fm`. Localized web subdomains are supported for share links, for example `https://es.files.fm/u/{folder_hash}` and `https://de.files.fm/u/{folder_hash}`.

### Routing model

The API is reachable through three URL styles. Knowing which style an endpoint uses avoids most "404 / wrong path" problems.

| Style | URL pattern | Maps to | Used by |
| --- | --- | --- | --- |
| V2 REST action | `https://api.files.fm/api_v2/{action}` | `api/v2/index.php?action={action}` (server rewrite) | All API V2 actions |
| V1 script | `https://api.files.fm/api/{script}.php` | `api/{script}.php` | Legacy V1 endpoints (login, keys, listing, tree, undelete, etc.) |
| Root-level script | `https://api.files.fm/{script}.php` | top-level script | `save_file.php`, `down.php`, `thumb*.php`, ZIP streamer |

The `api_v2/{action}` form is a clean-URL rewrite to the single dispatcher `api/v2/index.php`; the `action` may also be passed as a `GET`/`POST` parameter. Prefer `POST` for API parameters unless an endpoint explicitly documents `GET` as accepted. Successful REST responses are JSON unless the endpoint returns raw file content (such as `download_file`); a few legacy endpoints return plain text.

### Common Integration Flow

1. Generate an API key at `https://files.fm/account#api_keys` or use a dedicated user/service account.
2. Create a folder with `create_folder`; store `folder_hash`, `folder_edit_key`, and `folder_upload_key` in your own database.
3. Upload files with `upload_file` using authentication or the folder upload key.
4. List or inspect content with `get_folder_content`, `get_file_info`, and `get_folder_info`.
5. Download files with `download_file`.
6. Rename, move, delete, or restore files/folders as needed.

### Important Concepts

- Every file and folder has a unique hash. Store hashes and the corresponding edit/upload/delete keys in your own system.
- Keys and their meaning:
  - **Folder hash** identifies a folder (also called an "upload"). Example: `hash=polcdti`.
  - **File hash** identifies a file. Example: `i=jyphxsb` in download links.
  - **add_key** / `folder_upload_key` / `AddFileKey` allows uploading new files into a folder without full access.
  - **delete_key** / `folder_edit_key` / `DeleteKey` allows editing/deleting the folder and its files (subject to access rights).
  - **File edit/delete key** (`file_delete_key`) is used for file edits/replacements; a folder edit key also works where supported.
- **ROOT folder**: every account has exactly one ROOT folder (`DisplayName = "ROOT"`, `ParentID = 0`). It is always private, cannot be renamed or deleted, and is the default parent when you create a folder without `parent_folder_hash`. Its hash and keys are returned at login (see "ROOT folder and account info").
- Access types: `PRIVATE`, `LINK`, `PASSWORD`, and `PUBLIC` where supported.
  - `LINK` allows reading/listing/downloading by anyone who knows the hash/link.
  - `PRIVATE` requires authorization and explicit rights.
  - `PASSWORD` requires the folder password (passed as `password`).
- Files and folders created through the API can also be managed in the Files.fm UI at `https://files.fm/filebrowser`.
- API requests may be rate-limited or blocked by automated web firewall checks if request patterns look abusive.
- Business and Enterprise integrations needing higher limits, dedicated access rules, or production support should contact `support@files.fm`.

### Authorization

Authentication is handled centrally by `api/authenticate_user.php`, which is included by both the V2 router and the V1 scripts. It accepts the following methods (checked in roughly this order). Any one of them is enough; always use HTTPS.

| Method | How to send credentials | Notes |
| --- | --- | --- |
| `user` + `pass` (GET) | `?user=...&pass=...` | Username or email + password. Supported for compatibility; avoid putting secrets in URLs/logs. |
| `user` + `pass` (POST) | POST fields `user`, `pass` | Preferred over GET for credentials. |
| HTTP Basic authentication | `Authorization: Basic base64(user:pass)` header | Also read from the FastCGI `Authorization` header when `PHP_AUTH_USER`/`PHP_AUTH_PW` are not populated. |
| API access token | `user` + `user_access_token` (GET or POST) | Token for a user or dedicated service account. Generate/revoke at `https://files.fm/account#api_keys`. Recommended for automation. |
| Existing session cookie | Standard `PHPSESSID` cookie from a prior login | Supported by authenticated actions. |
| Session id parameter | `?PHPSESSID=...` or `?SessionID=...` | Use the session id without a cookie jar. |
| Google OAuth | `google_token` + `google_email` (GET or POST) | Verified ID token. First-time logins may auto-create an account (`first_name`, `last_name` optional). |
| Apple SSO | `apple_code` (GET or POST) | Authorization code exchanged with Apple; may auto-create an account on first login. |

When `authenticate_user.php` is called as a standalone endpoint (no `API_APP` constant), it returns a JSON object:

```json
{
  "Success": true,
  "Message": null,
  "SessionID": "PHPSESSID_VALUE"
}
```

#### Generating an API access token

Pass `get_user_access_token` to a successful login call (for example `api/login.php` or `api/authenticate_user.php`) to mint a token for the authenticated user; it is returned as `UserData.user_access_token`. Tokens can also be created and revoked in account settings at `https://files.fm/account#api_keys`. Keep tokens confidential and rotate them if leaked.

#### Two-factor authentication (2FA)

If the account requires 2FA, a successful credential check does not immediately grant a session. The API sends a confirmation link by email and waits briefly for the same IP to be confirmed:

- Standalone JSON response while pending: `{"Success": false, "Status": "two_factor_auth_required", "Message": "Two-factor auth required"}`.
- When included by another API script: the request exits with HTTP `403` and a `TWO_FACTOR_REQURIED: 1` header.

Confirm the emailed link from the same IP, then retry the request. A token-based login for a service account bypasses the 2FA demand.

#### Security notes

- Abusive or blacklisted source IPs and password-guessing patterns are throttled or blocked.
- Account creation via `api/register.php` is disabled; OAuth/SSO first-login auto-provisioning is the only API path that creates accounts.

### HTTP Status Codes

| Status | Meaning | Action |
| --- | --- | --- |
| `200 OK` | Request succeeded. | Process the returned JSON or binary content. |
| `400 Bad Request` | Invalid or incomplete parameters. | Check required parameters and formats. |
| `401 Unauthorized` | Authorization failed or is missing. | Check credentials, token, or session. |
| `403 Forbidden` | Authenticated user does not have access rights. | Change access type or share the resource with the user. |
| `405 Method Not Allowed` | Requested operation is not permitted for this resource. | Check file/folder hash and permissions. |
| `429 Too Many Requests` | Rate limit hit. | Wait for the rate limit to expire and retry later. |
| `500 Internal Server Error` | Backend/API service error. | Retry later or contact Files.fm support. |

### Endpoint Summary

These are all the actions accepted by the V2 router `api/v2/index.php`. All use the `/api_v2/{action}` URL. All require authorization except `upload_file` and `download_file` (which can also work with a folder upload key or LINK access respectively).

| Action | Method | Endpoint | Purpose |
| --- | --- | --- | --- |
| `create_folder` | `POST` | `/api_v2/create_folder` | Create a folder in ROOT or a parent folder. |
| `upload_file` | `POST multipart/form-data` | `/api_v2/upload_file` | Upload a file to an existing folder. |
| `download_file` | `POST` | `/api_v2/download_file` | Download raw file contents by file hash. |
| `delete_folder` | `POST` | `/api_v2/delete_folder` | Delete a folder. |
| `delete_file` | `POST` | `/api_v2/delete_file` | Delete a file. |
| `get_folder_content` | `POST` | `/api_v2/get_folder_content` | List files and subfolders in a folder. |
| `move_file` | `POST` | `/api_v2/move_file` | Move a file into another folder. |
| `get_file_info` | `POST` | `/api_v2/get_file_info` | Read file metadata. |
| `get_folder_info` | `POST` | `/api_v2/get_folder_info` | Read folder metadata. |
| `rename_file` | `POST` | `/api_v2/rename_file` | Rename a file. |
| `rename_folder` | `POST` | `/api_v2/rename_folder` | Rename a folder. |
| `get_esignatures` | `POST` | `/api_v2/get_esignatures` | List e-signatures for a file. |
| `esignature_share` | `POST` | `/api_v2/esignature_share` | Share a file for signing. |
| `save_user_encryption_keys` | `POST` | `/api_v2/save_user_encryption_keys` | Store a user's public encryption keys (E2E). |
| `save_file_encryption_key` | `POST` | `/api_v2/save_file_encryption_key` | Store the wrapped encryption key for a file (E2E). |
| `get_file_encryption_key` | `POST` | `/api_v2/get_file_encryption_key` | Retrieve the wrapped encryption key for a file (E2E). |
| `save_upload_encryption_key` | `POST` | `/api_v2/save_upload_encryption_key` | Store the wrapped encryption key for a folder (E2E). |
| `get_upload_encryption_key` | `POST` | `/api_v2/get_upload_encryption_key` | Retrieve the wrapped encryption key for a folder (E2E). |
| `get_share_encryption_key` | `POST` | `/api_v2/get_share_encryption_key` | Get a re-wrapped key for sharing a file/folder with another user (E2E). |

Restore/undelete is not a V2 action; use the legacy scripts `api/undelete_folder.php` and `api/undelete_file.php` (see "Legacy V1 Endpoints").

The metadata/listing actions `get_file_info`, `get_folder_info`, and `get_folder_content` accept an optional `get_access_rights` flag that adds an `access_rights` object to each item (see those endpoints).

## Quick Start

A minimal create -> upload -> list -> download flow. This uses the simple legacy V1 endpoints, which is the fastest way to get going; the equivalent V2 actions are documented later.

### 1. Create a folder

```text
GET /api/get_upload_id.php
```

```text
https://api.files.fm/api/get_upload_id.php?user=demo&pass=demo&folder_name=my_folder_name&access_type=LINK
```

The response includes a folder `hash` and keys (`add_key`, `delete_key`). Store them for later calls.

```json
{"hash":"rbzztfm","delete_key":"0fe4108e","add_key":"63dfe","UserID":11315}
```

Public folder link: `https://files.fm/u/{folder_hash}`. Public file link: `https://files.fm/f/{file_hash}`.

### 2. Upload a file

```text
POST /save_file.php?up_id={folder_hash}&key={add_key}&get_file_hash
```

```bash
curl -i -F 'file=@/tmp/local-file.txt' 'https://api.files.fm/save_file.php?up_id=jjqcank7&key=05123&get_file_hash'
```

Upload one file per request. With `get_file_hash`, the response is the uploaded file hash.

### 3. List folder contents

```text
GET /api/get_file_list_for_upload.php?hash={folder_hash}&include_folders=1
```

### 4. Download a file

```text
GET /down.php?i={file_hash}
```

### 5. Log in (session + ROOT keys)

```text
GET|POST /api/login.php?user=demo&pass=demo
```

## ROOT Folder and Account Info

Every account has a single ROOT folder: `DisplayName = "ROOT"`, `ParentID = 0`. It is always private, cannot be renamed or deleted, and is the implicit parent when `create_folder` is called without `parent_folder_hash`.

To obtain the ROOT hash/keys and account details, authenticate and request user data. Calling `api/authenticate_user.php` (standalone, with any auth method) returns a `UserData` object. Add `get_user_access_token` to also mint an API token.

```text
GET https://api.files.fm/api/authenticate_user.php?user=demo&pass=demo&get_user_access_token=1
```

`UserData` fields:

| Field | Description |
| --- | --- |
| `ID` | User id. |
| `UserName` | Username. |
| `Email` | Account email. |
| `first_name`, `last_name` | Account holder name. |
| `avatar_path`, `profile_background` | Public profile assets. |
| `root_upload_hash` | Hash of the ROOT folder. |
| `root_upload_key` | ROOT folder delete/edit key. |
| `root_add_key` | ROOT folder add-files key. |
| `mobile_camera_upload_hash` | Hash of the mobile camera upload folder, if any. |
| `current_location_country_code` | Lowercased country code derived from the request IP. |
| `file_size_limit` | Per-file upload size limit (bytes) for the account. |
| `queue_size_limit` | Upload queue size limit for the account. |
| `user_access_token` | Present only when `get_user_access_token` was requested. |

Note: the lightweight `api/login.php` endpoint returns the ROOT info as a plain-text cookie string (`PHPSESSID`, `user`, `hash`, `ID`, `email`, `root_upload_hash`, `root_upload_key`), not JSON. Use `api/authenticate_user.php` for the structured `UserData` object.

## REST Endpoints

### create_folder

Creates a new folder in the user's account and sets its access rights.

```text
POST https://api.files.fm/api_v2/create_folder
```

Authorization: mandatory.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `parent_folder_hash` | string | No | Parent folder hash. If omitted, the new folder is created in the authenticated user's ROOT folder. ROOT exists for all accounts and contains metadata such as `subfolder_count` and `file_count`. |
| `folder_name` | string | No | Folder name. If omitted, a random name is generated in `YYYY-MM-DD_folderhash` format. If the same name exists in the target path, Files.fm adds a suffix such as `NAME (1)`. |
| `access_type` | string | No | `LINK` or `PRIVATE`. `LINK` allows read/list access to anyone who knows the hash/link. `PRIVATE` allows access only to the owner and users with shared rights. |

Example:

```bash
curl -sS --max-time 25 -X POST 'https://api.files.fm/api_v2/create_folder' \
  -d 'user=YOUR_USERNAME' \
  -d 'user_access_token=YOUR_API_TOKEN' \
  -d 'folder_name=MY_FOLDER_NAME' \
  -d 'access_type=PRIVATE'
```

Success response:

```json
{
  "folder_hash": "xxxxxxxxx",
  "folder_edit_key": "xxxxxxxx",
  "folder_upload_key": "xxxxx",
  "folder_name": "Name given"
}
```

Response fields:

| Name | Type | Description |
| --- | --- | --- |
| `folder_hash` | string | Identifier of the created folder. |
| `folder_edit_key` | string | Key that grants permission to modify the folder. |
| `folder_upload_key` | string | Key that grants permission to upload files to the folder. |
| `folder_name` | string | Final folder name. If the requested name already existed, this may include a uniqueness suffix. |

Folder access link example:

```text
https://files.fm/u/{folder_hash}
```

Errors: standard status codes from the REST overview.

### upload_file

Uploads a file to an existing folder. Create a target folder before uploading. Do not upload files directly to ROOT; it is always private. Upload limits may apply by account tier.

```text
POST https://api.files.fm/api_v2/upload_file
Content-Type: multipart/form-data
```

Authorization: optional if `folder_upload_key` is provided and valid; otherwise authenticate the user.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `folder_hash` | string | Yes | Target folder hash. |
| `folder_upload_key` | string | No | Folder key that grants upload permission without full folder access. Required when not authenticating and using a known folder upload key. |
| `file` | binary | Yes | File content. PDF examples also show multipart fields such as `Filedata` and `fileToUpload`; use `file` unless your integration is based on an older example flow. |
| `watermark_text` | string | No | Text watermark for JPG/PNG uploads. |
| `watermark_position` | string | No | `TOP_LEFT`, `TOP_RIGHT`, `BOTTOM_LEFT`, or `BOTTOM_RIGHT`. |
| `watermark_color` | string | No | Watermark color. Default: `F0FF3C`. |

Upload using folder upload key:

```bash
curl -X POST 'https://api.files.fm/api_v2/upload_file' \
  -F 'folder_hash=TARGET_FOLDER_HASH' \
  -F 'folder_upload_key=TARGET_ADD_KEY' \
  -F 'file=@/path/to/local/file.pdf'
```

Upload using account credentials/token:

```bash
printf 'upload_file API test at %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" | \
curl -sS --max-time 40 -X POST 'https://api.files.fm/api_v2/upload_file' \
  -F 'user=YOUR_USERNAME' \
  -F 'user_access_token=YOUR_API_TOKEN' \
  -F 'folder_hash=TARGET_FOLDER_HASH' \
  -F 'file=@-;filename=api_v2_upload_test.txt;type=text/plain'
```

Success response:

```json
{
  "file_hash": "xxxxxxxxx",
  "file_delete_key": "xxxxxxxxx",
  "file_name": "api_v2_upload_test (2).txt",
  "timestamp_uploaded": 1777638342,
  "timestamp_last_modified": 1777638342
}
```

Response fields:

| Name | Type | Description |
| --- | --- | --- |
| `file_hash` | string | Identifier of the uploaded file. |
| `file_delete_key` | string | File edit/delete key. |
| `file_name` | string | Final stored file name. If a duplicate exists, Files.fm may add a suffix such as `(1)`. |
| `timestamp_uploaded` | integer | Upload timestamp. |
| `timestamp_last_modified` | integer | Last-modified timestamp. |

Additional upload-specific errors:

| Status | Message | Meaning | Action |
| --- | --- | --- | --- |
| `490` | Virus detected | Uploaded file was detected as infected and was not stored. | Do not retry unchanged; show an appropriate error. |
| `491` | File Name Double Extension | File name contains a double extension, for example `invoice.pdf.exe`. | Do not retry unchanged; show an appropriate error. |
| `492` | Folder Size Limit Exceeded | Upload would exceed the folder size limit. | Do not retry unchanged; reduce size or use a suitable account plan. |
| `493` | File Size Limit Exceeded | Uploaded file exceeds the file size limit. | Do not retry unchanged; reduce size or use a suitable account plan. |
| `494` | Partial upload | Full-size file was not received. | Retry after checking client/network timeout limits. |

Documented file-size limits:

| Account type | File-size limit |
| --- | --- |
| Enterprise | 50 GB or larger by agreement |
| Business | 50 GB or larger by agreement |
| Pro | 20 GB |
| Lifetime | 10 GB |
| Personal | 10 GB |
| Free | 5 GB |

Documented folder-size limits: Enterprise, Business, Pro, Lifetime, and Personal are unlimited; Free is 5 GB.

### download_file

Downloads raw file contents by file hash.

```text
POST https://api.files.fm/api_v2/download_file
```

Authorization:

| File access | Authorization |
| --- | --- |
| `PRIVATE` | Required. |
| `LINK` | Not required. The file can be downloaded or embedded without authentication. |

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file_hash` | string | Yes | File hash. |

Response:

- Success: raw binary file contents.
- `Content-Type`: automatically set based on file type.
- `Content-Disposition`: inline or attachment depending on client and access settings.

Public LINK example:

```text
https://files.fm/f/demo
```

Legacy V1 compatibility endpoint, available but not recommended for new integrations:

```text
https://api.files.fm/down.php?i=rktesv5b
```

Direct file path links may also be used where configured:

```text
https://files.fm/pa/username/folder1/subfolder/filename.jpg
```

Errors: standard status codes from the REST overview.

### delete_folder

Deletes a folder from a user account.

```text
POST https://api.files.fm/api_v2/delete_folder
```

Authorization: required.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `folder_hash` | string | Yes | Folder hash to delete. |

Response:

```json
{"status":"ok"}
```

or:

```json
{"status":"error"}
```

To restore a deleted folder, use the legacy `api/undelete_folder.php` script (see "Legacy V1 Endpoints"). Undelete is available for PRO, BUSINESS, and ENTERPRISE accounts.

Errors: standard status codes from the REST overview.

### delete_file

Deletes a file.

```text
POST https://api.files.fm/api_v2/delete_file
```

Authorization: required.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file_hash` | string | Yes | File hash to delete. |

Response: no additional data documented.

To restore a deleted file, use the legacy `api/undelete_file.php` script (see "Legacy V1 Endpoints"). Undelete is available for PRO, BUSINESS, and ENTERPRISE accounts.

Errors: standard status codes from the REST overview.

### get_folder_content

Returns the direct contents of a folder, including files and subfolders.

```text
POST https://api.files.fm/api_v2/get_folder_content
```

Authorization: required.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `folder_hash` | string | Yes | Folder hash whose contents should be listed. |
| `get_access_rights` | bool | No | When truthy, each item also includes an `access_rights` object (see below). |

Response: JSON array of file/folder objects.

```json
[
  {
    "type": "file",
    "hash": "xxxxxxxxx",
    "name": "example.pdf",
    "size": 12345,
    "timestamp_uploaded": 1777638342,
    "timestamp_last_modified": 1777638342,
    "delete_key": "xxxxxx",
    "add_files_key": null
  },
  {
    "type": "folder",
    "hash": "yyyyyyyyy",
    "name": "Subfolder",
    "size": 0,
    "timestamp_uploaded": 1777638342,
    "timestamp_last_modified": 1777638342,
    "delete_key": "yyyyyy",
    "add_files_key": "zzzzz"
  }
]
```

Response fields:

| Name | Type | Description |
| --- | --- | --- |
| `type` | string | `file` or `folder`. |
| `hash` | string | File or subfolder hash. |
| `name` | string | File or subfolder name. |
| `size` | integer | File or folder size in bytes. |
| `timestamp_uploaded` | integer | Upload timestamp. |
| `timestamp_last_modified` | integer | Last modification timestamp. |
| `delete_key` | string | File or folder edit/delete key if available. |
| `add_files_key` | string | Folder upload/add key for subfolders if available. |
| `access_rights` | object | Only when `get_access_rights` is set. For folders: `allow_view`, `allow_delete`, `allow_add`, `allow_edit`, `allow_download`. For files: `allow_view`, `allow_delete`, `allow_edit`, `allow_download`. |

Errors: standard status codes from the REST overview.

### move_file

Moves a file into another folder in the same account.

```text
POST https://api.files.fm/api_v2/move_file
```

Authorization: mandatory.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file_hash` | string | Yes | File hash to move. |
| `folder_hash` | string | Yes | Target folder hash. |

Response: no additional data documented.

Errors: standard status codes. Status `405` may be returned if the target folder does not exist or the operation is not allowed.

### get_file_info

Returns metadata for a file.

```text
POST https://api.files.fm/api_v2/get_file_info
```

Authorization: required.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file_hash` | string | Yes | File hash. |
| `get_access_rights` | bool | No | When truthy, the response also includes an `access_rights` object (`allow_view`, `allow_delete`, `allow_edit`, `allow_download`). |

Success response:

```json
{
  "hash": "xxxxxxxxx",
  "name": "example.pdf",
  "size": 12345,
  "timestamp_uploaded": 1777638342,
  "timestamp_last_modified": 1777638342,
  "delete_key": "xxxxxx",
  "parent_folder_hash": "yyyyyyyyy",
  "access_type": "LINK",
  "password_protected": false,
  "price_set": false
}
```

Response fields:

| Name | Type | Description |
| --- | --- | --- |
| `hash` | string | File hash. |
| `name` | string | File name. |
| `size` | integer | File size in bytes. |
| `timestamp_uploaded` | integer | Upload timestamp. |
| `timestamp_last_modified` | integer | Last modification timestamp. |
| `delete_key` | string or null | File edit/delete key. `null` is returned if the caller has no delete permission. |
| `parent_folder_hash` | string or null | Parent folder hash. `null` is returned if the caller cannot view the parent folder. |
| `access_type` | string | File access type (`PRIVATE`, `LINK`, `PASSWORD`, `PUBLIC`). If the file has no own access type, the parent folder's access type is returned. |
| `password_protected` | boolean | `true` when the parent folder has a password set (the password value is never returned). |
| `price_set` | boolean | `true` when the file has a download/sale price configured in `file_download_price` (the price amount is not returned). |

Errors: standard status codes from the REST overview.

### get_folder_info

Returns metadata for a folder.

```text
POST https://api.files.fm/api_v2/get_folder_info
```

Authorization: required.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `folder_hash` | string | Yes | Folder hash. |
| `get_access_rights` | bool | No | When truthy, the response also includes an `access_rights` object (`allow_view`, `allow_delete`, `allow_add`, `allow_edit`, `allow_download`). |

Success response:

```json
{
  "hash": "xxxxxxxxx",
  "name": "Folder name",
  "size": 12345,
  "timestamp_uploaded": 1777638342,
  "timestamp_last_modified": 1777638342,
  "delete_key": "xxxxxx",
  "parent_folder_hash": "yyyyyyyyy",
  "add_files_key": "zzzzz",
  "file_count": 10,
  "subfolder_count": 2,
  "access_type": "LINK",
  "password_protected": false,
  "price_set": false
}
```

Response fields:

| Name | Type | Description |
| --- | --- | --- |
| `hash` | string | Folder hash. |
| `name` | string | Folder name. |
| `size` | integer | Folder size in bytes. |
| `timestamp_uploaded` | integer | Upload/creation timestamp. |
| `timestamp_last_modified` | integer | Last modification timestamp. |
| `delete_key` | string or null | Folder edit/delete key. `null` is returned if the caller cannot delete the folder. |
| `parent_folder_hash` | string or null | Parent folder hash. `null` is returned if the caller cannot view the parent folder. |
| `add_files_key` | string or null | Upload/add key. `null` is returned if the caller cannot modify the folder. |
| `file_count` | integer | Number of files in the folder and subfolders. |
| `subfolder_count` | integer | Number of subfolders. |
| `access_type` | string | Folder access type (`PRIVATE`, `LINK`, `PASSWORD`, `PUBLIC`). |
| `password_protected` | boolean | `true` when the folder has a password set (the password value is never returned). |
| `price_set` | boolean | `true` when the folder has a download/sale price configured in `file_download_price` (the price amount is not returned). |

Errors: standard status codes from the REST overview.

### get_esignatures

Returns e-signature records for a file.

```text
POST https://api.files.fm/api_v2/get_esignatures
```

Authorization: required.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file_hash` | string | Yes | File hash whose e-signatures should be returned. |
| `from_date` | string | No | Inclusive start date filter for signature timestamps. |
| `to_date` | string | No | Inclusive end date filter for signature timestamps. |

Success response:

```json
[
  {
    "file_hash": "xxxxxxxxx",
    "signing_timestamp": "xxxxxxxxx",
    "signer_name": "Signer Name"
  }
]
```

Response fields:

| Name | Type | Description |
| --- | --- | --- |
| `file_hash` | string | File hash. |
| `signing_timestamp` | string | Datetime when the file was signed. |
| `signer_name` | string | Signer's name and surname. |

Errors: standard status codes from the REST overview.

### esignature_share

Shares a file to be signed by other users. Optional `next_share_emails` can prefill the next share dialog so the recipient can re-share the file.

```text
POST https://api.files.fm/api_v2/esignature_share
```

Authorization: required.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file_hash` | string | Yes | File hash that should be shared for signing. |
| `text` | string | No | Message included in the sharing email. |
| `emails` | string[] | Yes | Recipients that receive the signing request email. |
| `next_share_emails` | string[] | No | Email addresses prefilled for recipients that may re-share the signing request. |

Success response:

```json
{
  "status": "ok",
  "sent_emails": "person@example.com",
  "next_share_emails": "next@example.com"
}
```

Response fields:

| Name | Type | Description |
| --- | --- | --- |
| `status` | string | Request status. |
| `sent_emails` | string | Comma-separated list of emails that received the signing request. |
| `next_share_emails` | string | Comma-separated list of emails prefilled for the next share step. |

Errors: standard status codes from the REST overview.

### rename_file

Renames an existing file and returns the final stored filename.

```text
POST https://api.files.fm/api_v2/rename_file
```

Authorization: required. Supported auth methods are the same as other API V2 actions, including `user` + `pass`, valid session, and token/session flows supported by Files.fm authentication.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file_hash` | string | Yes | File hash to rename. |
| `file_name` | string | Yes | Desired new file name. |

Access and behavior:

- Caller must have edit rights for the file.
- Deleted or missing files return an error.
- The filename is normalized and made unique inside the folder.
- If the requested name equals the current name, API returns success with unchanged name.

Success response:

```json
{
  "file_hash": "ahgavbqr2d",
  "file_name": "renamed_from_curl_test.txt"
}
```

`file_name` is the final name after normalization and uniqueness handling.

Common errors:

| Status | Meaning |
| --- | --- |
| `400 Bad Request` | Missing `file_hash` or `file_name`. |
| `401 Unauthorized` | Caller is not authenticated. |
| `405 Method Not Allowed` | File not found or caller has no edit permission. |
| `500 Internal Server Error` | Unexpected backend error. |

Example:

```bash
curl -X POST 'https://api.files.fm/api_v2/rename_file' \
  --data-urlencode 'file_hash=YOUR_FILE_HASH' \
  --data-urlencode 'file_name=New file name.pdf' \
  --data-urlencode 'user=YOUR_USERNAME' \
  --data-urlencode 'pass=YOUR_PASSWORD'
```

### rename_folder

Renames an existing folder that the authenticated user is allowed to edit.

```text
POST https://api.files.fm/api_v2/rename_folder
```

Authorization: required.

Parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `folder_hash` | string | Yes | Folder hash to rename. |
| `folder_name` | string | Yes | Desired new folder name. |
| `name` | string | No | Alias for `folder_name`. If both are sent, `folder_name` is used. |

Access and behavior:

- Caller must be authenticated.
- Folder must exist and must not be deleted.
- Caller must have folder `allow_edit` rights.
- ROOT folder (`ParentID = 0`) cannot be renamed.
- Folder name is normalized and made unique inside the parent folder.
- Successful rename triggers the standard folder change event pipeline, including ETag/update side effects.

Success response:

```json
{
  "folder_hash": "dkjse72whr",
  "folder_name": "rf_evt_renamed_1777640861"
}
```

`folder_name` is the final name after normalization and uniqueness handling.

Common errors:

| Status | Meaning |
| --- | --- |
| `400 Bad Request` | Missing `folder_hash` or `folder_name`. |
| `401 Unauthorized` | Authentication missing or invalid. |
| `405 Method Not Allowed` | Folder does not exist, user has no edit rights, or root folder rename was attempted. |
| `500 Internal Server Error` | Unexpected server-side failure, such as DB/event processing error. |

Example:

```bash
curl -X POST 'https://api.files.fm/api_v2/rename_folder' \
  --data-urlencode 'folder_hash=YOUR_FOLDER_HASH' \
  --data-urlencode 'folder_name=New folder name' \
  --data-urlencode 'user=YOUR_USERNAME' \
  --data-urlencode 'pass=YOUR_PASSWORD'
```

## End-to-End Encryption Key Endpoints

These advanced V2 actions support client-side end-to-end encryption (E2E) of files and folders. They store and retrieve wrapped (encrypted) symmetric keys and the public keys needed to unwrap them. Files.fm uses a hybrid post-quantum scheme: each user publishes a KEM public key (key encapsulation), a DSA public key (signatures), plus classical `x25519` and `ed25519` public keys. The server only stores public keys and already-wrapped key material; it never sees plaintext content keys.

These endpoints are primarily used by the Files.fm web client. They are documented here for completeness; most integrations do not need them.

Common rules for all six actions:

- `POST` to `https://api.files.fm/api_v2/{action}`.
- Authorization is required, and `userID` must equal the authenticated user's id, otherwise `403`.
- Standard error status codes apply (`400` missing parameter, `403` mismatch/permission, `404` not found, `500` failure).

### save_user_encryption_keys

Stores the authenticated user's public encryption keys.

```text
POST https://api.files.fm/api_v2/save_user_encryption_keys
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `userID` | integer | Yes | Must match the authenticated user. |
| `kem` | string | Yes | KEM public key. |
| `dsa` | string | Yes | DSA public key. |
| `x25519` | string | Yes | X25519 public key. |
| `ed25519` | string | Yes | Ed25519 public key. |

Success response:

```json
{"success": true}
```

### save_file_encryption_key

Stores the wrapped encryption key for a file (owner is both sender and receiver). Marks the file as encrypted. Requires edit rights on the file.

```text
POST https://api.files.fm/api_v2/save_file_encryption_key
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `userID` | integer | Yes | Must match the authenticated user. |
| `fileHash` | string | Yes | Target file hash. |
| `encryptionKey` | string | Yes | Wrapped (encrypted) content key. |
| `keySignature` | string | Yes | Signature over the wrapped key. |
| `fileSignature` | string | No | Optional signature over the file. |

Success response:

```json
{"success": true}
```

### get_file_encryption_key

Returns the wrapped encryption key and the sender's public keys for a file. Requires download rights on the file. Set `isEncryptedFolder` when the file lives in an encrypted folder so the owner-created key is returned.

```text
POST https://api.files.fm/api_v2/get_file_encryption_key
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `userID` | integer | Yes | Must match the authenticated user. |
| `fileHash` | string | Yes | Target file hash. |
| `isEncryptedFolder` | bool | No | If true, fetch the key created by the encrypting user. |

Success response:

```json
{
  "encryptionKey": "...",
  "keySignature": "...",
  "fileSignature": "...",
  "senderPublicKEMKey": "...",
  "senderPublicDSAKey": "...",
  "senderPublicX25519Key": "...",
  "senderPublicED25519Key": "...",
  "senderUserID": 11315
}
```

### save_upload_encryption_key

Stores the wrapped encryption key for a folder (upload). Marks the folder as encrypted. Requires edit rights on the folder.

```text
POST https://api.files.fm/api_v2/save_upload_encryption_key
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `userID` | integer | Yes | Must match the authenticated user. |
| `uploadHash` | string | Yes | Target folder hash. |
| `encryptionKey` | string | Yes | Wrapped (encrypted) content key. |
| `keySignature` | string | Yes | Signature over the wrapped key. |

Success response:

```json
{"success": true}
```

### get_upload_encryption_key

Returns the wrapped encryption key and the sender's public keys for a folder. Requires download rights on the folder. Set `isEncryptedFolder` to fetch the owner-created key.

```text
POST https://api.files.fm/api_v2/get_upload_encryption_key
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `userID` | integer | Yes | Must match the authenticated user. |
| `uploadHash` | string | Yes | Target folder hash. |
| `isEncryptedFolder` | bool | No | If true, fetch the key created by the encrypting user. |

Success response:

```json
{
  "encryptionKey": "...",
  "keySignature": "...",
  "senderPublicKEMKey": "...",
  "senderPublicDSAKey": "...",
  "senderPublicX25519Key": "...",
  "senderPublicED25519Key": "...",
  "senderUserID": 11315
}
```

### get_share_encryption_key

Returns the caller's wrapped key for a file or folder plus the recipient's public keys, so the client can re-wrap the content key for sharing. Provide exactly one of `fileHash` or `uploadHash`. Requires download rights on the shared item.

```text
POST https://api.files.fm/api_v2/get_share_encryption_key
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `userID` | integer | Yes | Must match the authenticated user. |
| `receiverEmail` | string | Yes | Email of the user to share with (must have published encryption keys). |
| `fileHash` | string | Conditional | File hash to share (use this or `uploadHash`). |
| `uploadHash` | string | Conditional | Folder hash to share (use this or `fileHash`). |

Success response:

```json
{
  "encryptionKey": "...",
  "keySignature": "...",
  "receiverKEMKey": "...",
  "receiverDSAKey": "...",
  "receiverX25519Key": "...",
  "receiverED25519Key": "...",
  "receiverUserID": 44961
}
```

## Legacy V1 Endpoints

These endpoints predate API V2. They remain fully supported and many have no V2 equivalent (thumbnails, recursive tree, ZIP download, versions, sharing, embedding). They live under `https://api.files.fm/api/{script}.php` (or at the root for `save_file.php`, `down.php`, `thumb*.php`). All of them authenticate through `api/authenticate_user.php`, so any auth method from the Authorization section works. Most return JSON; a few return plain text (noted per endpoint).

### Authentication and session (V1)

#### login.php

```text
GET|POST https://api.files.fm/api/login.php?user=demo&pass=demo
```

Logs the user in and returns a plain-text cookie string with the session and ROOT folder info:

```text
cookie:PHPSESSID=...; user=demo; hash=...; ID=11315; email=demo@example.com; root_upload_hash=...; root_upload_key=...
```

Returns `error: incorrect login` on failure. For a structured JSON `UserData` object (and to mint an API token), call `api/authenticate_user.php` instead (see "ROOT Folder and Account Info").

#### sesslogin.php

```text
GET|POST https://api.files.fm/api/sesslogin.php?PHPSESSID=...&username=demo&redirect_url=https://files.fm/filebrowser
```

Cross-domain web login helper: validates the session and `redirect_url` (must be a `failiem.lv`/`files.fm`/`files.me`/`file.fm` host), logs the user in on the current and partner domains, then issues an HTTP redirect. Intended for browser SSO flows, not REST clients.

#### validate_session.php

```text
GET https://api.files.fm/api/validate_session.php
```

Returns whether the current session is logged in:

```json
{"Success": true, "Message": null, "SessionID": "..."}
```

#### test_session.php

```text
GET https://api.files.fm/api/test_session.php
```

Prints the `_COOKIE` and `_SESSION` arrays. Used only for internal development/diagnostics. NA.

### Folders: create and keys (V1)

#### get_upload_id.php (create folder)

```text
GET https://api.files.fm/api/get_upload_id.php
```

Creates a folder and returns its hash and keys. This is the backend behind the V2 `create_folder` action.

Parameters: `user`, `pass` (optional), `folder_name` (optional), `parent_hash` (optional, defaults to ROOT when authenticated), `access_type` (`PRIVATE` or `LINK`).

```text
https://api.files.fm/api/get_upload_id.php?user=demo&pass=demo&folder_name=My_Folder&parent_hash=fkf4m8yc
```

```json
{"hash":"vdidqcw","delete_key":"789e5ed4","add_key":"b0977","UserID":44961,"FolderName":"my_foldername"}
```

If used anonymously, `UserID` may be `false`, and the anonymous folder is auto-deleted after about one month.

#### get_upload_keys.php

```text
GET https://api.files.fm/api/get_upload_keys.php?hash=polcdti&user=demo&pass=demo
```

Returns the folder's add and delete keys:

```json
{"AddFileKey":"3e7ee","DeleteKey":"4d7bb256"}
```

#### get_add_key.php

```text
GET https://api.files.fm/api/get_add_key.php?hash=polcdti
```

Requires an active user session. Returns only the folder add key:

```json
{"add_key":"3e7ee"}
```

#### get_file_keys.php

```text
GET https://api.files.fm/api/get_file_keys.php
```

Returns file edit keys (a folder edit key also works where supported). Contact Files.fm for full documentation and enabled access.

#### get_ids_and_keys_from_paths.php

```text
POST https://api.files.fm/api/get_ids_and_keys_from_paths.php?upload_hash={parent_hash}&add_key={parent_add_key}
```

Resolves a list of directory paths under a parent folder to their ids and add keys, creating any missing folders. POST `Directories[]` entries (one path per entry). Optional `access_type` (`PRIVATE`, `LINK`, `PASSWORD`, `PUBLIC`) and `addto`/`addhash` for public-upload contexts.

```json
{
  "Success": true,
  "Directories": {
    "/test": {"id": 123, "add_key": "abc"},
    "/test/sub1": {"id": 234, "add_key": "bcd"}
  },
  "Error": null
}
```

### Files: upload and replace (V1)

#### save_file.php (upload)

```text
POST https://api.files.fm/save_file.php?up_id={folder_hash}&key={add_key}&get_file_hash
```

Uploads one file (multipart field `file`). This is the backend behind the V2 `upload_file` action. With `get_file_hash`, returns the new file hash. Optional `watermark_text` (and related watermark params) for image uploads. Upload one file per request.

```bash
curl -i -F 'file=@/tmp/local-file.txt' 'https://api.files.fm/save_file.php?up_id=trgkzgp&key=a3f8a&get_file_hash'
```

#### save_file.php (replace)

```text
POST https://api.files.fm/save_file.php?up_id={folder_hash}&key={add_key}
```

Pass `do=update` and `replace_file_hash={file_hash}` to replace an existing file. Supports file versions for BUSINESS and ENTERPRISE accounts; the ETag changes after replacement. Contact Files.fm for the full replacement flow.

### Listing and metadata (V1)

#### get_file_list_for_upload.php (List folder child items)

```text
GET https://api.files.fm/api/get_file_list_for_upload.php?hash={folder_hash}&include_folders=1
```

Returns direct child files/folders and metadata for one folder (not recursive). This is the backend behind the V2 `get_folder_content` action.

```json
[{"hash":"jyphxsb","name":"File1.jpg","Size":"106361"},{"hash":"yewpddm","name":"File2.jpg","Size":"62249"}]
```

Empty folder returns `[]`.

**Anonymous link access.** This V1 endpoint also accepts unauthenticated requests for folders whose access type is `LINK` or `PUBLIC`: pass only the folder `hash` (no credentials). The listing is strictly view-only — `delete_key`/`add_key` are never returned, `PRIVATE` folders and password-protected folders (without a session password) are rejected, and `PRIVATE` files inside a public folder are filtered out. To deter enumeration of the short folder hash, anonymous requests are rate-limited per IP (HTTP `429` / `{"error":"rate_limited"}` when exceeded) and intentionally delayed by ~2 seconds each. Authenticated requests (session, `user`+`pass`, or `user`+`user_access_token`) are not throttled or delayed. The V2 `get_folder_content` action does **not** allow anonymous access — it always requires authentication.

#### get_upload_tree.php (recursive tree / search)

```text
GET https://api.files.fm/api/get_upload_tree.php?Hash={folder_hash}&DeleteKey={folder_delete_key}
```

Returns all subdirectories and their contents recursively, with file/folder metadata. Also used as the basis for folder search.

```json
{
  "error": null,
  "data": {
    "Type": "Folder", "ID": "4759592", "Hash": "eklywcn",
    "AddFileKey": "30ae5", "DeleteKey": "f686ee67", "ParentID": "4962316",
    "CreatedDate": "2014-02-20 22:55:30", "ModifiedDate": null, "Name": "eklywcn1",
    "Children": [
      {"Type": "Folder", "ID": "4799549", "Hash": "gvznfga", "AddFileKey": "e5a1f", "DeleteKey": "d94bf9b9", "ParentID": "4759592", "CreatedDate": "2014-03-01 18:50:13", "ModifiedDate": null, "Name": "aaabbbcccd112233", "Children": false}
    ]
  }
}
```

#### upload_list.php (ROOT children)

```text
GET https://api.files.fm/api/upload_list.php?user=demo&pass=demo
```

Returns the direct children of the user's ROOT folder (metadata only, no add/delete keys): `hash`, `date`, `description`, `files`, `size`, `views`, `valid_to_date`.

```json
[{"hash":"polcdti","date":"2012-12-05 19:00:19","description":"","files":"2","size":"168610","views":"1","valid_to_date":""}]
```

#### get_file_info.php

Two modes:

```text
GET  https://api.files.fm/api/get_file_info.php?hash={file_hash}&del_key={file_delete_key}
POST https://api.files.fm/api/get_file_info.php   (action=get_file_hash_by_name)
```

The GET mode returns rich file metadata (requires the file's delete key):

```json
{"success": true, "file_info": {"Name": "photo.jpg", "ContentType": "image/jpeg", "Extension": "jpg", "ExtensionType": "image", "Size": "106361", "RealSize": 106361, "CustomInfo": {"Width": 1024, "Height": 768}}}
```

The POST mode (`action=get_file_hash_by_name`, `upload_hash`, `file_name`; requires a logged-in user with view rights) resolves a file name to its hash:

```json
{"success": true, "file_info": {"hash": "jyphxsb"}}
```

#### get_uploads_exist.php

```text
POST https://api.files.fm/api/get_uploads_exist.php
```

Authenticated. POST a JSON body `{"hashes": ["...","..."]}` and receive a map of folder hash to existence (only folders owned by the user with an add key count as existing):

```json
{"8mj6vv99": true, "qpyh3b8u": true, "s3yyrrtz": false}
```

#### get_storage_data.php

```text
GET https://api.files.fm/api/get_storage_data.php
```

Authenticated. Returns the signed-in user's storage usage and quota (MB):

```json
{"success": true, "message": null, "data": {"used_mb": 5.39, "quota_mb": "2000", "available_mb": "2000", "free_mb": 1994.61}}
```

### Search (web/ajax)

#### ajax/search.php

```text
GET|POST https://files.fm/ajax/search.php
```

Full-text search across the authenticated user's files and folders (own, shared, in a specific folder, and optionally deleted items). Served from the `files.fm` web host and authenticated by session, so pass `PHPSESSID` as a cookie or query parameter. Storage subscribers are searched via the Sphinx full-text index; other accounts fall back to a SQL `LIKE` search. Two request styles are supported.

1. Simplified API mode (recommended for integrations). Pass `result_format=JSON` and `query`; the script builds the search definition and returns a clean JSON array. Optionally pass `folder_hash` to restrict the search to one folder (subfolders included). When `folder_hash` is omitted or set to ROOT, it searches your own files plus organization-shared files.

```text
GET https://files.fm/ajax/search.php?result_format=JSON&query=document&PHPSESSID=YOUR_SESSION_ID
```

2. Full mode (used by the file browser UI). Pass a URL-encoded `search_json` object plus table paging/sorting parameters.

```text
GET https://files.fm/ajax/search.php?search_json=%7B...%7D&PHPSESSID=...&table_page=0&table_size=1000&table_column[3]=1
```

The decoded `search_json` from the file-browser example:

```json
{
  "Mode": "simple",
  "Query": "document",
  "Types": {},
  "Sections": { "MY": true, "SHARED_WITH_ME": true, "DELETED": false, "THIS_FOLDER": false },
  "ThisFolder": ""
}
```

`search_json` fields:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `Mode` | string | Yes | `simple` or `advanced`. |
| `Query` | string | Yes (simple) | Search phrase, minimum 2 characters. |
| `Types` | object | Yes (simple) | Type filter. Keys: `DOCUMENTS`, `IMAGES`, `VIDEO`, `MUSIC`, `FOLDERS`, `FILES` (booleans). Empty `{}` searches all types. |
| `Sections` | object | Yes | Where to search. Keys: `MY`, `SHARED_WITH_ME`, `SHARED_WITH_ME_ONLY_ORGANIZATION`, `DELETED`, `THIS_FOLDER` (booleans). At least one must be true. `DELETED` is ignored unless the user is a storage subscriber. |
| `ThisFolder` | string | Conditional | Folder hash to search in. Required when `Sections.THIS_FOLDER` is true. |
| `Operator` | string | Yes (advanced) | `AND` or `OR`. |
| `Criteria` | array | Yes (advanced) | Advanced criteria, each `{ Field, Operator, Query, AdditionalParam }`. Contact Files.fm for the full field/operator list. |

Other query parameters:

| Name | Type | Description |
| --- | --- | --- |
| `result_format` | string | `JSON` (clean array, recommended), `OWNCLOUD` (Nextcloud/ownCloud unified-search structure), or omitted for `WEB_TABLESORTER` (pre-rendered HTML rows used by the web UI). |
| `query` | string | Simplified-mode search phrase (alternative to `search_json`). |
| `folder_hash` | string | Simplified-mode folder restriction. |
| `table_size` | integer | Results per page, `1`-`1000` (default `1000`). |
| `table_page` | integer | Zero-based page number. |
| `table_column[<index>]` | integer | Sort column and direction (`0` = ascending, otherwise descending). Index: `2` = name, `4` = size, `5` = owner, `6` = views; other indexes sort by modification date. |
| `NoSubfolders` | bool | Do not search subfolders. |
| `get_access_rights` | bool | With `result_format=JSON`, add an `access_rights` object to each item. |
| `PHPSESSID` | string | Session id (if not sent as a cookie). |

`result_format=JSON` response: a JSON array of result items.

```json
[
  {
    "type": "file",
    "name": "document.pdf",
    "hash": "jyphxsb",
    "size": 12345,
    "mod_date": "2026-05-01 12:00:00",
    "path": "/folder/sub/document.pdf",
    "public_access_type": "PRIVATE",
    "parent_hash": "polcdti",
    "content_type": "application/pdf",
    "file_count": null,
    "subfolder_count": null,
    "access_rights": null
  }
]
```

Response fields (`result_format=JSON`):

| Name | Type | Description |
| --- | --- | --- |
| `type` | string | `file` or `folder`. |
| `name` | string | File or folder name. |
| `hash` | string | File or folder hash. |
| `size` | integer | Size in bytes. |
| `mod_date` | string | Last modification datetime. |
| `path` | string | Full path of the item. |
| `public_access_type` | string | `PUBLIC` (LINK/PUBLIC) or `PRIVATE`. |
| `parent_hash` | string | Parent folder hash. |
| `content_type` | string or null | MIME type for files; `null` for folders. |
| `file_count` | integer or null | File count for folders; `null` for files. |
| `subfolder_count` | integer or null | Subfolder count for folders; `null` for files. |
| `access_rights` | object or null | Present only with `get_access_rights`. |

The default `WEB_TABLESORTER` response is an object `{ "status": "ok", "total_rows": N, "headers": [...], "rows": [...], "page_count": N, "total_time": 0.12 }` where `rows` contain pre-rendered HTML for the web UI. Errors return `{ "status": "error" }`.

### Rename and access type (V1)

#### change_file.php (rename file)

```text
GET|POST https://api.files.fm/api/change_file.php?file_hash={file_hash}&folder_hash={folder_hash}&file_display_name=NewName.txt
```

Updates a file's display name.

```json
{"Success":true,"Error":null,"Message":"Fields updated"}
```

#### change_upload.php (rename folder)

```text
GET|POST https://api.files.fm/api/change_upload.php?Hash={folder_hash}&upload_display_name=New%20Name
```

Authenticated; requires edit rights. Renames a folder (`DisplayName`). The ROOT folder cannot be renamed. You may pass `UploadID` instead of `Hash`.

```json
{"Success":true,"Error":null,"Message":null}
```

#### upload_access_type.php (change folder access type)

```text
GET https://api.files.fm/api/upload_access_type.php?h={folder_hash}&type=PRIVATE
```

Authenticated; requires permission. `type` is one of `PRIVATE`, `PASSWORD`, `LINK`, `PUBLIC`.

```json
{"success": true, "error": ""}
```

### Delete and restore (V1)

#### delete_file.php

```text
GET|POST https://api.files.fm/api/delete_file.php?hash={file_hash}&del_key={delete_key}
```

Deletes a file by hash and delete key (the key may be the parent folder delete key or the file's own key). This is the backend behind the V2 `delete_file` action.

```json
{"success":1}
```

Failure returns `{"success":0}`. Legacy combined endpoint: `GET https://api.files.fm/list.php?i={folder_hash}&k={delete_key}&f={file_hash}`.

#### delete_upload.php (delete folder)

```text
GET|POST https://api.files.fm/api/delete_upload.php?u={folder_hash}&del_key={delete_key}
```

Deletes a folder (and its files/subfolders) owned by the authenticated user. This is the backend behind the V2 `delete_folder` action. Optional `delete_only_subfolders=1` deletes only the subfolders. Supports `jsonp`/`callback`.

```json
{"success":1,"error":0,"deleted_id":1234}
```

Failure returns `{"success":0,"error":1,"deleted_id":null}`. Legacy combined endpoint: `GET https://api.files.fm/list.php?i={folder_hash}&k={delete_key}&t=ok`.

#### multi_delete.php

```text
POST https://api.files.fm/api/multi_delete.php
```

Authenticated. Deletes many files and folders in one transaction. POST JSON `{"items": {"files": ["..."], "folders": ["..."]}}`, up to 200 items per call. Rolls back if any item fails or the user lacks delete rights.

```json
{"success": true, "error": "", "error_code": null}
```

#### undelete_file.php

```text
GET|POST https://api.files.fm/api/undelete_file.php?hash={file_hash}
```

Restores a deleted file. Requires a logged-in paying user (storage subscriber). Optional `return_new_path=true` and `return_new_folder_id=true` add path/folder info to the response.

```json
{"status":"ok"}
```

#### undelete_folder.php

```text
GET|POST https://api.files.fm/api/undelete_folder.php?hash={folder_hash}
```

Restores a deleted folder (and its recoverable files). Requires a logged-in paying user. Optional `return_new_path=true`. Returns `{"status":"ok"}` or `{"status":"error"}`. Undelete is available for PRO, BUSINESS, and ENTERPRISE accounts; the restoration window depends on account type.

#### multi_restore.php

```text
POST https://api.files.fm/api/multi_restore.php
```

Authenticated. Restores many deleted files/folders owned by the user. POST JSON `{"items": {"files": ["..."], "folders": ["..."]}}`, up to 200 items per call.

```json
{"success": true, "error": "", "error_code": null}
```

#### delete_items_from_recyclebin.php (permanent delete)

```text
POST https://api.files.fm/api/delete_items_from_recyclebin.php
```

Permanently deletes items from the recycle bin. Authenticated; requires the account `password` for confirmation. POST `password` and `items` = `{"files": ["..."], "folders": ["..."]}`.

```json
{"status":"ok"}
```

Incorrect password returns `{"status":"error","error_code":1}`. This is destructive and not recoverable.

#### restore_version_file.php (file versions)

```text
GET https://api.files.fm/api/restore_version_file.php?hash={file_hash}&del_key={delete_key}&version_id={version_id}
```

Restores a previous version of a file as the current version. Requires a logged-in user. File versions are a BUSINESS/ENTERPRISE feature.

### Download, thumbnails, and previews (V1)

#### down.php (download)

```text
GET https://api.files.fm/down.php?i={file_hash}
```

Downloads a file by hash. This is the backend behind the V2 `download_file` action. Direct download limits depend on account type and security settings.

#### thumb.php (small thumbnail)

```text
GET https://api.files.fm/thumb.php?i={file_hash}
```

Small image thumbnail, approximately `400x271 px`.

#### Large thumbnails

```text
GET https://api.files.fm/thumb_show.php?i={file_or_folder_hash}
GET https://api.files.fm/thumb_video_picture.php?i={file_hash}
GET https://api.files.fm/thumb_folder.php?i={folder_hash}
```

Large thumbnails (approximately `1500 px`) for images, video poster frames, and folder covers.

#### Streamable video preview / document PDF preview

Files.fm can generate an MP4 streaming preview (HD or custom quality; watermarked when a price is set) and PDF previews for document/archive formats (DOC, XLS, EDOC, ZIP, etc.). Requires the file hash and enabled access. Contact Files.fm for full documentation. See also the "previews and conversion" integration section.

#### Download folder as ZIP

```text
GET https://api.files.fm/server_scripts/zip/zip_streamer/upload_zip_streamer.php?uhash={folder_hash}
```

Streams all files in a folder as a ZIP. For password-protected folders add `&password=my_password`. Limits may apply.

#### embed_urls.php (path-access URL)

```text
GET https://api.files.fm/api/embed_urls.php?i={file_hash}
```

Returns the human-readable path-access URL for a file:

```json
{"path_access_url": "https://files.fm/pa/username/folder1/subfolder/filename.jpg"}
```

#### Share links (browser preview)

```text
https://files.fm/u/{folder_hash}
https://files.fm/f/{file_hash}
```

Localized domains are supported, for example `https://es.files.fm/u/{folder_hash}` and `https://de.files.fm/u/{folder_hash}`.

### Sharing management

Files.fm sharing grants named recipients (registered users, email addresses, or — for enterprise organizations — organization user groups) fine-grained access to a file or folder. Access rights are stored per recipient in `upload_sharing`: `CanView`, `CanRead` (download), `CanWrite` (edit), `CanAdd`, `CanDelete`, and `CanShare`. Two endpoints cover the lifecycle: `ajax/share.php` creates shares (and sends notification emails), and `api/sharing.php` lists and adjusts existing shares.

Both are session-authenticated (pass `PHPSESSID`); they are the same pipeline the V2 `esignature_share` action builds on.

#### ajax/share.php (grant access)

```text
POST https://files.fm/ajax/share.php
```

Grants access to one or more recipients on a single file or folder, optionally sends share-notification emails, and (for end-to-end encrypted items) stores per-recipient wrapped encryption keys. Served from the `files.fm` web host and authenticated by session.

Target the item with one of:

- `file_view_hash` (or `file_hash`) — share a single file.
- `upload_hash` — share a folder.

Parameters (POST):

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `items[]` | array | Yes | Recipients. Each entry is an object `{ value, item_type }`. `item_type` is `email` (then `value` is an email address) or `org_user` (then `value` is a Files.fm user id in your organization). |
| `file_view_hash` / `file_hash` | string | Conditional | File hash to share (use this or `upload_hash`). |
| `upload_hash` | string | Conditional | Folder hash to share. |
| `rights[view]` | bool | No | Allow preview/view (maps to `CanView`). |
| `rights[download]` | bool | No | Allow download (`CanRead`). |
| `rights[write]` | bool | No | Allow edit/upload (`CanWrite`). |
| `rights[add]` | bool | No | Allow adding files (`CanAdd`). |
| `rights[delete]` | bool | No | Allow delete (`CanDelete`). |
| `rights[share]` | bool | No | Allow re-sharing (`CanShare`). |
| `description` | string | No | Message included in the share email. |
| `submit` | string | Yes | Must be `1` to perform the share; other values validate recipients only. |
| `send_share_email` | string | No | `0` to suppress the notification email (default sends). |
| `send_notification_once_open` | string | No | `0` to disable the "link opened" notification (default on). |
| `save_share_message` | string | No | `1` to save the message as the user's default. |
| `date_active_from` / `date_active_to` | string | No | Time-limited access window; `from` must be `<=` `to`. |
| `next_share_emails[]` | array | No | Additional emails to chain-share to the same item. |
| `external_user_group` | int | No | Enterprise only: external user group that newly added external users are placed in. |
| `encryption_key`, `key_signature` | string | No | For E2E-encrypted items: the recipient-wrapped key and its signature. |

Granting the delete right (and folder add/write rights) causes the generated share URL to embed the corresponding delete/add keys.

Response:

```json
{
  "status": "ok",
  "items": {
    "user@example.com": {
      "item_type": "email",
      "value": "user@example.com",
      "email": "user@example.com",
      "is_valid_email": true,
      "user_id": 12345,
      "org_id": 0,
      "can_email": true,
      "have_to_send_enterprise_invite_email": false,
      "enterprise_invite_email_link": ""
    }
  },
  "message": null,
  "invalid_emails": "",
  "unsubscribed_emails": "",
  "sent_emails": "user@example.com"
}
```

`status` is `ok` on success or `error` on failure. `message` may be `null`, `no-access-rights`, `already_shared`, `marked_as_spam`, `free_emails_exhausted`, or `wrong_dates`. `items` is keyed by each recipient's `value`.

Security note: the share URLs returned and emailed can embed file/folder delete and add keys depending on the granted rights — treat the response and the emails as sensitive.

#### sharing.php (sharing modal and management)

```text
GET https://api.files.fm/api/sharing.php?Action={action}&...
```

Session-authenticated endpoint that backs the sharing dialog: it lists existing shares for an item and toggles individual access rights. The session user must hold the `allow_sharing` right on the target item.

Select the item with one of `UploadID`, `FileID`, `UploadHash`, `FileHash`, or `DvsDocumentId`.

Actions (`Action` parameter):

| Action | Returns | Description |
| --- | --- | --- |
| `GetModalWindow` | `{ Success, HTML }` | Rendered HTML of the share modal for the item. |
| `GetSharingTable` | `{ Success, HTML, ItemNameHTML, ProjectTeamInfo }` | Rendered HTML table of all current shares (users, emails, organization user groups, external groups) with each assignee's rights and active dates. Enterprise accounts also receive project team info. |
| `UpdateUploadSharing` | `{ Success, AccessRights }` | Toggle a single access right for one assignee. |

`UpdateUploadSharing` parameters:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `AssigneeType` | string | Yes | One of `USER` (organization user), `ANY_USER`, `EMAIL`, `ORG_USER_GROUP`, `ORG_EXTERN_USER_GROUP`. |
| `AssigneeUserID` | int | Yes | Id of the assignee (user id, email id, or group id). |
| `AccessRightName` | string | Yes | One of `CanRead`, `CanWrite`, `CanDelete`, `CanView`, `CanShare`, `CanAdd`. |
| `AccessRightStatus` | int | Yes | `1` to grant, `0` to revoke. |

```json
{"Success": true, "AccessRights": {"CanView": 1, "CanRead": 1, "CanWrite": 0, "CanDelete": 0, "CanShare": 0, "CanAdd": 0}}
```

Setting all rights to `0` effectively removes an assignee's access — there is no separate delete-share endpoint. `GetModalWindow` and `GetSharingTable` return pre-rendered HTML for the web UI rather than structured data, so for programmatic listing build on `UpdateUploadSharing` plus your own bookkeeping.

> Organization role/module permissions (the org RBAC table updated by `api/permissions.php`) are a separate concern from per-file sharing and belong to the Organization Management API (out of scope here).

#### save_sharing_confirmation.php

```text
GET https://api.files.fm/api/save_sharing_confirmation.php?item_type=FILE&item_id={id}&confirm=1
```

Confirms (or declines) a pending share for the authenticated user (or via a signed `user_id`+`hash` link). `item_type` is `FILE` or `UPLOAD`; set `confirm=1` to accept. Optional `redirect_after_save=1` redirects to the file browser instead of returning JSON.

```json
{"Success": true, "Error": null, "Message": null}
```

### Utility and account (V1)

#### Disabled endpoints

Account creation via `api/register.php` is disabled. New accounts are created through the website or OAuth/SSO first-login auto-provisioning.

### Other Files.fm APIs

Organization and dealer management has its own separate API, documented in `Files.fm_OrgManagement_API.pdf` (served from the `api/` directory) and implemented by `api/manage_organizations.php`. It is out of scope for this document. Additional subsystems (WebDAV, Document Management/DVS, Chat, Metadata, AI) are integration-specific; contact `support@files.fm`.

## Supplemental Integration Sections

The remaining sections come from the same PDF and document related options: embedded e-signature forms, Files.fm AI endpoint usage, pre-built upload forms, embedding, previews, conversion, watermarking, and server-side AI analysis.

## E-Signature Form Integration

The Files.fm e-signature form can be integrated into your system using JavaScript and embedded as an
iframe within your website or web application.

The embedded form communicates with your application through callback events, enabling seamless
interaction and status handling during the signing process. This allows users within your IT environment to
digitally sign files stored in Files.fm using supported electronic signature methods, including the Latvian State
Radio and Television Centre (LVRTC) e-signature and Smart-ID, when enabled for the corresponding business
account.

In addition to embedded usage, Files.fm also supports generating secure signing links that can be shared
with external parties. These links allow recipients to sign documents without requiring access to your
internal systems or a Files.fm user account, making the solution suitable for both internal workflows and
external document signing scenarios.

https://files.fm/api/demo/esigning_api_demo_v.2.0/

The integration example is written in the web programming language PHP and can be downloaded here:
https://files.fm/u/4dcrp5wy3

How to use the example:

1)     Download the file "esigning_api_demo_v.2.0.zip".
2)     Unzip this file and place it on your computer in web server's ( Apache + PHP ) folder.
3)     Open the config.php file and enter your Files.fm account username and password.
4)     Open the index.php file through your browser.

### Initializing the form

To initialize the e-signature form on the client side in the browser, on your page:

1) JavaScript resources must be included (for example, in the HTML head tag of the page):

```html
<script type="text/javascript" src="https://api.files.fm/esignature/form.js"></script>
```

2) Create a JavaScript object of the class `FailiemlvEsignatureForm`, passing the form settings. All settings are optional.

```js
objMyFailiemlvEsignatureForm = new FailiemlvEsignatureForm({
    callbacks: {
        on_signing_finished: function (result) { /* ... */ },
        on_form_closed: function (data) { /* ... */ }
    },
    emobile_signing: {
        open_new_tab: false
    },
    allowed_signing_formats: {
        edoc: true,
        pdf: true,
        asice: false
    },
    default_signing_format: "edoc",
    signature_validation: {
        enabled: true
    },
    sign_files_separate: {
        allow_select: true,
        default: false
    }
});
```

#### Form settings parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `callbacks` | object | No | Your JavaScript functions called after specific events in the form. |
| `callbacks.on_signing_finished` | function | No | Called when the user finishes signing (see "Receiving the signing result"). |
| `callbacks.on_form_closed` | function | No | Called when the user closes the form (see "Receiving the form close event"). |
| `emobile_signing` | object | No | Settings for the eParaksts mobile signing process. |
| `emobile_signing.open_new_tab` | boolean | No | Whether eParaksts mobile signing opens eparaksts.lv in a new browser tab instead of redirecting the current page. |
| `allowed_signing_formats` | object | No | Allowed file signing formats. |
| `allowed_signing_formats.edoc` | boolean | No | Allow signing files in `edoc` format. |
| `allowed_signing_formats.pdf` | boolean | No | Allow signing files in `pdf` format. |
| `allowed_signing_formats.asice` | boolean | No | Allow signing files in `asice` format. |
| `default_signing_format` | string | No | Default signing format: `edoc`, `pdf`, or `asice`. |
| `signature_validation` | object | No | Settings for checking existing signatures in a file. |
| `signature_validation.enabled` | boolean | No | Whether to check and show existing signatures when the form opens. |
| `sign_files_separate` | object | No | Settings for signing multiple files: all in one file, or each in a separate file. |
| `sign_files_separate.allow_select` | boolean | No | Whether the user may choose the multi-file signing type. |
| `sign_files_separate.default` | boolean | No | Default multi-file method. `false` = all in one file; `true` = each in a separate file. |

### Opening the form

Before opening the form on the server side of the client system, the files to be signed must be uploaded
using the Files.fm data API.

If you need to sign multiple files :

1)      a new folder must be created (see Request for folder creation - create_folder );
2)      The files to be signed must be uploaded to the created folder (see Request for file upload - upload_file
).

If you need to sign a single file :

1) select an existing folder in your Files.fm account or create a new folder (see Request for folder creation
- create_folder ) to which to upload the file;
2) The file to be signed must be uploaded to the created or existing folder (see Request for file upload -
upload_file ).

The form can be opened by calling the showForm function on the previously created object of the class
FailiemLv_eSignature_Form .

To sign multiple files, pass the folder of the uploaded files:

```js
objMyFailiemlvEsignatureForm.showForm( folder_hash, folder_edit_key );
```

To sign a single file, pass the file instead:

```js
objMyFailiemlvEsignatureForm.showForm( null, null, file_hash, file_delete_key );
```

#### Function parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `folder_hash` | string | Conditional | Folder identifier. Required when signing multiple files. |
| `folder_edit_key` | string | Conditional | Folder edit key. Required when signing multiple files. |
| `file_hash` | string | Conditional | File identifier. Required when signing a single file. |
| `file_delete_key` | string | Conditional | File edit/delete key. Required when signing a single file. |

### Receiving the signing result

As mentioned above, Initializing the Form , when initializing the form (creating a JavaScript object
of the form), you must specify a callback function on your page in the parameters , which should
be called when the signing process is complete ("on_signing_finished").
When calling this function, its first parameter will be passed an object with data about the signing result. The
signing can be successful or unsuccessful.

#### Signing result object data

| Name | Type | Description |
| --- | --- | --- |
| `success` | boolean | Whether signing was successful. |
| `folder_hash` | string | Folder identifier of the signed files. Only when signing multiple files. |
| `file_hash` | string | File identifier of the signed file. Only when signing a single file. |
| `signed_file_format` | string | Format/extension of the signed file. Only on success. |
| `signed_file_hash` | string | Identifier of the signed file. Returned on success when signing a single file, or multiple files as "all in one file". |
| `signed_file_delete_key` | string | Signed file edit/delete key. Same conditions as `signed_file_hash`. |
| `signed_file_hashes` | array | Array of signed file data. Returned on success when signing multiple files "each file individually". |
| `signed_file_hashes[].original_file_name` | string | Name of the original file. |
| `signed_file_hashes[].signed_file_hash` | string | Identifier of the signed file. |
| `signed_file_hashes[].signed_file_delete_key` | string | Signed file edit/delete key. |

Upon receiving a notification that the signing has been completed, if the signing has been successful, you
can download the signed files from the Files.fm system and save them to your system .

It is recommended to download the file on the server side of your system with an API request (see Request
for file download - download_file ).

After downloading the signed files, it is recommended to delete the previously uploaded file folder or file
from the Files.fm system by making a Delete API request from your system server . (see Request for deleting

a folder - delete_folder ). The folder or file identifier is passed in the function call parameter ("folder_hash",
"file_hash").

It is also recommended to delete the folder after an unsuccessful signing.

### Receiving the form close event

As mentioned above , Initializing a Form , when initializing a form (creating a JavaScript
object of the form), you must specify a callback function on your page in the parameters
that should be called when the user closes the form (" on_form_closed ").
When calling this function, its first parameter will be passed an object with data about the file folder or file
opened in the form:

- if signing is performed for multiple files , an object with data about the folder opened in the form
will be submitted;
- If signing is performed for a single file , an object with data about the file opened in the form will be
passed.

#### File or folder data opened in the form

| Name | Type | Description |
| --- | --- | --- |
| `folder_hash` | string | Identifier of the folder of files to be signed. |
| `file_hash` | string | Identifier of the file to be signed. |

Upon receiving a form closing notification, it is recommended to delete the previously uploaded file folder or
file from the Files.fm system via your system's server side with an API request (see Request to delete a folder
- delete_folder ). The folder or file identifier is passed in the function call parameter ("folder_hash",
"file_hash").

## Files.fm AI API (Ollama-compatible)

Files.fm provides a hosted Ollama-compatible Large Language Model API at `https://ai.files.fm`. It is a drop-in replacement for Ollama's HTTP interface, so existing tools, SDKs, and automation platforms (such as n8n) can use Files.fm-hosted models without running local GPU infrastructure, in a GDPR-compliant way. It follows the standard Ollama `/api/generate` and `/api/chat` schema and semantics. For automations, prefer the `https://ai.files.fm/api/generate` endpoint. Generate your API keys at `https://files.fm/account#api_keys`.

#### Supported models

| Model | Purpose |
| --- | --- |
| `gpt-oss:20b` | General-purpose text generation and reasoning. |
| `gemma3:latest` | Lightweight, fast instruction-following model. |
| `deepseek-ocr:latest` | OCR and text extraction from images. |
| `qwen3-vl:latest` | Vision-language model (image + text understanding). |

Model aliases use the `:latest` tag to allow transparent backend upgrades. If you need other models, ask us.

#### Authentication

Authentication uses a Bearer token in the HTTP `Authorization` header:

```text
Authorization: Bearer UserID:RandomString
```

- `UserID` is the Files.fm user id (for example, a service account used for automation).
- `RandomString` is the API token (generated in account settings or issued by a Files.fm account manager).
- Keep tokens confidential and stored securely. Disable old tokens and generate new ones if a token is lost.

#### Endpoints

```text
POST https://ai.files.fm/api/generate
POST https://ai.files.fm/api/chat
```

Headers:

```text
Content-Type: application/json
Authorization: Bearer UserID:RandomString
```

#### Request format (Ollama-compatible)

The request body follows the standard Ollama format (see `https://docs.ollama.com/api/introduction`).

| Field | Description |
| --- | --- |
| `model` | Model name (see supported models above). |
| `prompt` | Prompt text (used by `/api/generate`). |
| `messages` | Chat messages array of `{role, content}` (used by `/api/chat`). |
| `think` | Reasoning level (`low` recommended for automation). |
| `stream` | Streaming mode (set `false` for most integrations). |

Example — `/api/generate` with `gpt-oss:20b`:

```bash
curl --location 'https://ai.files.fm/api/generate' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer UserID:RandomString' \
  --data '{
    "model": "gpt-oss:20b",
    "prompt": "What is Files.fm? Answer in one sentence.",
    "think": "low",
    "stream": false
  }'
```

Example — `/api/chat`:

```bash
curl --location 'https://ai.files.fm/api/chat' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer UserID:RandomString' \
  --data '{
    "model": "gpt-oss:20b",
    "messages": [
      { "role": "user", "content": "What is Files.fm? Answer in one sentence." }
    ],
    "think": "low",
    "stream": false
  }'
```

Example — `gemma3:latest`:

```bash
curl --location 'https://ai.files.fm/api/chat' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer UserID:RandomString' \
  --data '{
    "model": "gemma3:latest",
    "messages": [
      { "role": "user", "content": "What is Files.fm? Answer in one sentence." }
    ],
    "stream": false
  }'
```

#### `/api/generate` response format

When `stream` is `false`, the API returns a JSON object (see `https://docs.ollama.com/api/generate`):

```json
{ "response": "Generated text output from the model.", "done": true }
```

| Field | Type | Description |
| --- | --- | --- |
| `response` | string or object | Generated output from the model. |
| `done` | boolean | Indicates that generation has completed. |

#### `/api/chat` response format

The response matches Ollama's standard structure:

```json
{
  "message": {
    "role": "assistant",
    "content": "Files.fm is a secure cloud storage and file sharing platform for individuals and businesses."
  }
}
```

The generated content is available at `message.content`.

### Using Files.fm AI with n8n

Use Files.fm AI inside n8n for automation tasks such as text summarization, classification, OCR post-processing, internal AI assistants, and document/form analysis. The HTTP Request node provides maximum compatibility and control.

n8n HTTP Request configuration:

| Setting | Value |
| --- | --- |
| Method | `POST` |
| URL | `https://ai.files.fm/api/generate` |
| Header `Content-Type` | `application/json` |
| Header `Authorization` | `Bearer UserID:RandomString` |
| Body Content Type | JSON |

Body example:

```json
{
  "model": "gpt-oss:20b",
  "prompt": "Summarize the following text in one concise sentence",
  "think": "low",
  "stream": false
}
```

Response:

```json
{ "response": "generated text" }
```

Extract the generated output with the expression `{{$json.response}}`. It can be forwarded to email nodes, Slack/Microsoft Teams, databases or CRMs, Files.fm document workflows, or webhooks/APIs.

Operational notes:

- The API is stateless; no session handling is required.
- Streaming is optional but not recommended for automation workflows.
- Designed for server-side and backend use.
- Suitable for GDPR-sensitive environments (EU-hosted).
- No local GPU, model downloads, or runtime management required.

## Pre-Built File Upload Form

For rapid and straightforward file upload integration, Files.fm provides a pre-built, configurable file upload
form that can be embedded into your website or application-similar in concept to the e-signature form.

This approach enables you to receive uploaded files quickly without implementing a full custom upload flow,
while still allowing configuration and customization per use case.

#### Key Capabilities

The pre-built upload form supports:

- Single-button or multi-step file uploads

- Custom input fields for collecting metadata alongside uploaded files

- Folder-based file organization

- Secure, link-based access control

- Seamless integration with existing Files.fm storage and workflows

#### Use Cases

The upload form is well suited for scenarios such as:

- Collecting files from external users or customers

- Receiving documents, images, or videos with structured metadata

- Rapid prototyping or low-code integrations

- Replacing custom upload implementations with a managed solution

The form can be configured to match your specific requirements, including the number of fields, validation
rules, and destination folders.

Learn more and configure your form: https://files.fm/upload-form

See an example in action: https://files.fm/demopro/?upload

## Additional Resources and Examples

If you need further clarification, contact `support@files.fm`. The V2 format is preferred; feel free to request additional information or features.

- Basic file upload example (raw code): `https://files.fm/api/demo/`
- Inspect the upload form flow (e.g. in Chrome DevTools): `https://files.fm/upload_iframe.php?uid=15802530&uid_hash=YOUR_UID_HASH`

### Embedding folder contents (gallery)

Embed a folder as a slideshow iframe:

```html
<iframe src="https://files.fm/u/cecguq8jzq&view=slideshow&autoplay=false" height="315" width="100%" style="max-width:560px; border:1px solid transparent;"></iframe>
```

Or embed via the gallery script tag:

```html
<script type="text/javascript" src="https://files.fm/gallery_module/v1/js/?hash=eax7jg9y3&user=13b73&ihash=YOUR_IHASH&view=horizontal" id="files_fm_upload_script_tag"></script>
```

### File conversion and previews

Files.fm automatically generates previews and converted formats for a wide range of file types. Previews enable fast viewing, embedding, and content inspection without downloading the original files. All preview generation is handled server-side within the Files.fm infrastructure.

#### Image previews and thumbnails

For image files (including RAW formats), Files.fm generates JPEG-based previews in multiple sizes:

- Thumbnail (small) - optimized for lists and galleries.
- Preview (normal) - resized image, typically up to ~1500 px on the longest edge.

These are available for embedding and quick viewing while preserving the original file unchanged.

#### Document previews

PDF documents can be previewed directly in the browser using the built-in PDF viewer, without downloads.

Files.fm can generate PDF previews for common office and document formats, including but not limited to:

```text
.doc, .docx, .odp, .ods, .odt, .pps, .ppsx, .ppt, .pptx,
.rtf, .xls, .xlsx, .dotx, .asice, .edoc, .zip
```

Text-based files can be previewed directly in the browser or downloaded as-is. Supported formats include:

```text
.txt, .php, .js, .html, .css, .xml, .csv, .ini, .log,
.asp, .asm, .c, .cc, .cmake, .cpp, .cs, .h, .java, .jsp,
.json, .pl, .py, .rb, .script, .sh, .swift, .sql, .vb,
.xhtml, .xsd, .xsl, .yaml, .yml, .inf
```

#### Video previews and streaming

For video files, Files.fm provides automatic preview and streaming support:

- If a video is not in MP4 format, or the original MP4 exceeds supported bitrate thresholds, Files.fm can generate a streaming-optimized MP4 preview.
- Preview videos are suitable for in-browser playback and embedding.

For large-scale or high-traffic video hosting, Files.fm recommends the Files.fm JavaScript Video Player, which supports P2P-assisted streaming to optimize bandwidth usage and performance.

### Applying a watermark

Files.fm supports text-based watermarks on JPEG and PNG images. Apply one by including the `watermark_text` parameter in the `save_file.php` request, for example `&watermark_text=YourTextHere`.

When a price is set or removed for an image or video file, Files.fm automatically regenerates the file previews (thumbnails) and applies a watermark using the file owner's username. This ensures consistent branding and content protection for monetized or restricted-access media.

### AI analysis (server-side)

Files.fm provides server-side AI processing for images, videos, audio, and text content stored on the platform. All analysis runs within the Files.fm infrastructure - no client-side processing or external AI services are required.

Depending on account type and configuration, the platform can perform:

- Optical Character Recognition (OCR) - extracting text and numbers from images and video frames.
- Image and video content analysis - object detection, face detection, and scene understanding.
- Automatic content description - AI-generated summaries and captions.
- Auto-tagging and categorization - generation of searchable metadata.
- Sentiment and emotion analysis - of detected faces or textual content.
- Text analysis with LLMs - summarization, classification, translation, and semantic analysis of documents and text files.

Processing model:

- All AI features operate asynchronously and server-side.
- Results are stored as metadata associated with files and can be used for search, filtering, moderation, or automation workflows.
- No raw data is sent to third-party AI providers unless explicitly agreed.

Availability - AI features are optional and may require specific account plans or add-ons, feature enablement by Files.fm, and additional configuration depending on use case (e.g. face recognition, moderation, OCR pipelines). For availability, configuration, or API-level access, contact `support@files.fm`.
