# Files.fm Document Management System (DMS) API

Files.fm provides a **Document Management System (DMS)** for organizing business documents with metadata, workflows, reminders, e-signatures, and access control integrated with cloud file storage.

The DMS API currently covers **tasks** (create, read, update, comment), **projects** (read-only: fields, users, and document lists), **contact persons** (create, read, update), and **clients / parties** (read-only: fields, users, and document lists). Other DMS registers are not available through this API yet. Data created or updated here is the same data shown in the DMS web interface.

> **Note:** Only `dvs_section=task`, `dvs_section=project_2`, `dvs_section=contact_person`, and `dvs_section=client` are supported. Additional registers and actions are planned. 

---

## Base URL

```text
https://api.files.fm/api_dvs/{dvs_section}/{action}
```

Example:

```text
POST https://api.files.fm/api_dvs/task/create_document
```

---

## Authentication

Authenticate every request with `user` and `user_access_token`. Always use HTTPS.

| Field | Description |
| --- | --- |
| `user` | Files.fm username or email |
| `user_access_token` | API access token. Generate/revoke at `https://files.fm/account#api_keys`. |

Send both in a JSON body (`Content-Type: application/json`) next to the action parameters. Do not put credentials in the URL. Do not send `pass`. A website login cookie by itself is not accepted.

```bash
curl -X POST 'https://api.files.fm/api_dvs/task/get_fields' \
  -H 'Content-Type: application/json' \
  -d '{"user":"YOUR_USER","user_access_token":"YOUR_API_TOKEN"}'
```

### Organization and DMS requirements

Beyond authentication, the DMS API has two additional requirements:

1. **Organization membership:** the authenticated user must belong to an organization that has DMS enabled.
2. **Section write permission:** the user's user-group must have `write` permission on the target DMS register (`dvs_section`). Read-only users cannot currently reach the DMS API.

If either requirement is not met, the API returns HTTP `405`.

---

## Request format

The URL names the register and the action. Send action-specific parameters in a JSON body (`Content-Type: application/json`). `user` and `user_access_token` in that JSON are used for authentication and are not treated as document fields.

```text
https://api.files.fm/api_dvs/{dvs_section}/{action}
```

| Path segment | Description |
| --- | --- |
| `{dvs_section}` | Register name: `task`, `project_2`, `contact_person`, or `client` (see [Supported registers](#supported-registers)) |
| `{action}` | Operation name (see [Endpoint summary](#endpoint-summary)) |

For actions with no extra parameters (for example `get_fields`), the JSON body only needs `user` and `user_access_token`. Prefer the URL path for `action` and `dvs_section`; do not rely on overriding them from the body.

---

## HTTP status codes

| Status | Meaning | Action |
| --- | --- | --- |
| `200 OK` | Request succeeded. | Process the returned JSON. |
| `400 Bad Request` | Invalid or incomplete parameters. | Check required parameters and formats. |
| `401 Unauthorized` | Authorization failed or is missing. | Check `user` and `user_access_token`.
| `405 Method Not Allowed` | Operation not permitted (missing section write permission, section not enabled for the org, or wrong HTTP method). | Check permissions, `dvs_section`, and method. |
| `500 Internal Server Error` | Backend/API service error. | Retry later or contact Files.fm support. |

On error, the response body is empty. Use the HTTP status code (and status text) to determine the failure; there is no JSON error payload.

---

## Supported registers

The `{dvs_section}` path segment must be one of the values below. Any other section returns HTTP `400` (`Invalid DVS section`).

| `dvs_section` | Register | Supported actions |
| --- | --- | --- |
| `task` | Tasks (project tasks) | `get_fields`, `get_users`, `get_document`, `get_documents`, `create_document`, `update_document`, `add_comment` |
| `project_2` | Projects (parent container for tasks) | `get_fields`, `get_users`, `get_document`, `get_documents` |
| `contact_person` | Contact persons (external notification receivers on tasks) | `get_fields`, `get_document`, `get_documents`, `create_document`, `update_document` |
| `client` | Clients / parties (companies and partners) | `get_fields`, `get_users`, `get_document`, `get_documents` |

`create_document` and `update_document` are available for **tasks** and **contact persons**. `add_comment` is **tasks only**. Projects and clients are read-only through this API.

Use `contact_person` `get_documents` / `get_document` to look up contact IDs, then pass those IDs as `ext_notif_receiver` when creating or updating a task. You can also create or update contact persons through this API.

Use `client` `get_documents` / `get_document` to look up client document IDs for contact `company` (and other relation fields that reference `client`).

---

## Endpoint summary

| Action | Method | Endpoint | Purpose |
| --- | --- | --- | --- |
| `get_fields` | `POST` | `/api_dvs/{dvs_section}/get_fields` | Field schema and dropdown options for create/update/filter. |
| `get_users` | `POST` | `/api_dvs/{dvs_section}/get_users` | Assignable users (for tasks: scoped to a project). |
| `get_document` | `POST` | `/api_dvs/{dvs_section}/get_document` | Read one document by ID. |
| `get_documents` | `POST` | `/api_dvs/{dvs_section}/get_documents` | List/filter documents with pagination. |
| `create_document` | `POST` | `/api_dvs/{dvs_section}/create_document` | Create a document (`task`, `contact_person`). |
| `update_document` | `POST` | `/api_dvs/{dvs_section}/update_document` | Partially update a document (`task`, `contact_person`). |
| `add_comment` | `POST` | `/api_dvs/task/add_comment` | Add a comment on a task (same as the web UI). Use `@[USER:user_id]` in the text to mention a user. |

`{dvs_section}` is `task`, `project_2`, `contact_person`, or `client` for the read actions (`get_users` is `task`, `project_2`, and `client` only). Write actions are `task` and `contact_person` (`add_comment` is `task` only).

---

## Actions

### `get_fields`

Returns the field schema for a register: field names, labels, types, whether the field is required, and the available options for dropdown fields. Use this to discover what fields to pass to `create_document` / `update_document` and which fields support filtering in `get_documents`.

```text
POST https://api.files.fm/api_dvs/task/get_fields
```

Request body: authorization only.

**Response:**

```json
{
  "fields": [
    {
      "name": "dvs_project_id",
      "label": "Project",
      "type": "relation",
      "required": true,
      "filter": true,
      "section": "project_2",
      "list_action": "get_documents"
    },
    {
      "name": "name",
      "label": "Name",
      "type": "text",
      "required": true,
      "filter": false
    },
    {
      "name": "dropdown_status",
      "label": "Status",
      "type": "dropdown",
      "required": false,
      "filter": true,
      "options": [
        { "id": 12, "display_name": "Open" },
        { "id": 13, "display_name": "In progress" },
        { "id": 14, "display_name": "Done" }
      ]
    },
    {
      "name": "responsible",
      "label": "Responsible",
      "type": "user_id",
      "required": false,
      "filter": false,
      "depends_on": "dvs_project_id",
      "list_action": "get_users"
    },
    {
      "name": "followers",
      "label": "Followers",
      "type": "user_ids",
      "required": false,
      "filter": false,
      "depends_on": "dvs_project_id",
      "list_action": "get_users"
    },
    {
      "name": "ext_notif_receiver",
      "label": "External followers",
      "type": "relation_ids",
      "required": false,
      "filter": false,
      "section": "contact_person",
      "list_action": "get_documents"
    }
  ]
}
```

#### Field types

| Type | Description | Input format (create/update) | Output format (get_document/get_documents) |
| --- | --- | --- | --- |
| `text` | Plain text or numeric string | string | `"value"` or `null` |
| `date` | Calendar date | `"YYYY-MM-DD"` string | `"YYYY-MM-DD"` or `null` |
| `html` | Rich text (HTML markup) | HTML string | Full HTML string (only in `get_document`; omitted in `get_documents`) |
| `dropdown` | Org-specific enum value | integer id from `options` | `{ "id": N, "display_name": "..." }` or `null` |
| `dropdown_ids` | Multiple org-specific enum values | array of integer ids from `options` | array of `{ "id", "display_name" }` objects |
| `relation` | Link to a document in another register | integer document id | `{ "id": N, "display_name": "..." }` or `null` |
| `relation_ids` | Multiple links to documents in another register | array of integer document ids | array of `{ "id", "display_name" }` objects |
| `user_id` | Single assignable user | integer user id from `get_users` | `{ "id": N, "display_name": "Full Name" }` or `null` |
| `user_ids` | Multiple assignable users | array of integer user ids | array of `{ "id", "display_name" }` objects |

Fields with `"filter": true` can be used as filters in `get_documents`. Fields with `"depends_on"` require the named field's value to be supplied when calling `get_users`.

Fields with `"list_action": "get_users"` contain user references; call `get_users` with the relevant context parameters to get the allowed values. Fields with `"list_action": "get_documents"` contain references to documents in another register; call `get_documents` on that register (see `"section"`) to list possible values.

---

### `get_users`

Returns assignable platform user IDs for `user_id` and `user_ids` fields in the current register. Only available on registers that expose those field types (`task`, `project_2`, `client`); not on `contact_person` (use `get_documents` there for contact document IDs). For tasks, the list is scoped to workers of the specified project.

```text
POST https://api.files.fm/api_dvs/task/get_users
Content-Type: application/json
```

**Request:**

```json
{
  "dvs_project_id": 51
}
```

| Parameter | Required for | Description |
| --- | --- | --- |
| `dvs_project_id` | `task` | ID of the project whose workers are listed. Required for task; not needed for `project_2` or `client`. |

**Response:**

```json
{
  "users": [
    { "id": 1042, "display_name": "Anna Smith" },
    { "id": 1105, "display_name": "John Doe" }
  ]
}
```

---

### `get_document`

Returns a single document by its DMS document ID.

```text
POST https://api.files.fm/api_dvs/task/get_document
Content-Type: application/json
```

**Request:**

```json
{
  "dvs_document_id": 4821
}
```

**Response:**

```json
{
  "dvs_document_id": 4821,
  "full_number": "PROJ-7",
  "dvs_project_id": { "id": 51, "display_name": "Website redesign" },
  "dropdown_type": null,
  "name": "Write API documentation",
  "description": "<p>Document all DMS API endpoints.</p>",
  "dropdown_priority": { "id": 17, "display_name": "High" },
  "dropdown_status": { "id": 12, "display_name": "In progress" },
  "responsible": { "id": 1042, "display_name": "Anna Smith" },
  "followers": [
    { "id": 1105, "display_name": "John Doe" }
  ],
  "ext_notif_receiver": [
    { "id": 901, "display_name": "Jane Client" }
  ],
  "date_due": "2026-09-30",
  "estimated_hours": "4",
  "spent_hours": null,
  "creator": { "id": 980, "display_name": "Maria Admin" },
  "date_created": "2026-08-10 14:22:05",
  "date_updated": "2026-08-24 09:45:11"
}
```

The `html` field type (`description`) is returned in full only for `get_document`. It is omitted from `get_documents` list results.

The `creator`, `date_created`, and `date_updated` fields are read-only metadata returned on get, not accepted in `get_fields` for create/update.

---

### `get_documents`

Returns a paginated list of documents in a register, with optional filtering.

```text
POST https://api.files.fm/api_dvs/task/get_documents
Content-Type: application/json
```

**Request:**

```json
{
  "limit": 20,
  "offset": 0,
  "filters": {
    "dvs_project_id": 51,
    "dropdown_status": [12, 13]
  }
}
```

| Parameter | Type | Default | Maximum | Description |
| --- | --- | --- | --- | --- |
| `limit` | integer | 50 | 200 | Number of results to return |
| `offset` | integer | 0 | — | Number of results to skip |
| `filters` | object | — | — | Only fields marked `"filter": true` in `get_fields`. Multiple values for one field are OR; multiple fields are AND. |

**Response:**

```json
{
  "items": [
    {
      "dvs_document_id": 4821,
      "full_number": "PROJ-7",
      "dvs_project_id": { "id": 51, "display_name": "Website redesign" },
      "dropdown_type": null,
      "name": "Write API documentation",
      "dropdown_priority": { "id": 17, "display_name": "High" },
      "dropdown_status": { "id": 12, "display_name": "In progress" },
      "responsible": { "id": 1042, "display_name": "Anna Smith" },
      "followers": [],
      "ext_notif_receiver": [],
      "date_due": "2026-09-30",
      "estimated_hours": "4",
      "spent_hours": null,
      "creator": { "id": 980, "display_name": "Maria Admin" },
      "date_created": "2026-08-10 14:22:05",
      "date_updated": "2026-08-24 09:45:11"
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}
```

Results are ordered by creation date descending (newest first).

To look up a contact ID for task `ext_notif_receiver`, call `get_documents` on `contact_person`. The contact list can be filtered by `company` and `multi_dropdown_group` (`"filter": true` in `get_fields`).

To look up a client ID for contact `company`, call `get_documents` on `client`. The client list can be filtered by dropdown fields, `multi_dropdown_group`, and `projectmanager` (`"filter": true` in `get_fields`).

---

### `create_document`

Creates a new document. Only fields declared by `get_fields` are accepted; unknown fields are ignored. Available for `task` and `contact_person`.

```text
POST https://api.files.fm/api_dvs/task/create_document
Content-Type: application/json
```

Auth: `user` and `user_access_token` in this JSON.

**Request:**

```json
{
  "user": "YOUR_USER",
  "user_access_token": "YOUR_API_TOKEN",
  "create_params": {
    "dvs_project_id": 51,
    "name": "Review pull request",
    "dropdown_priority": 17,
    "dropdown_status": 12,
    "responsible": 1042,
    "followers": [1105],
    "ext_notif_receiver": [901],
    "date_due": "2026-09-15",
    "estimated_hours": "2"
  }
}
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `create_params` | object | Yes | Document field values keyed by field name |

All fields declared as `"required": true` by `get_fields` must be present and non-empty. Fields marked `"required": false` may be omitted; the register sets sensible defaults.

User fields (`user_id`, `user_ids`) must contain IDs returned by `get_users`. Dropdown fields (`dropdown`, `dropdown_ids`) must contain option IDs returned by `get_fields`. Relation fields (`relation`, `relation_ids`) must contain document IDs from the register named in `"section"` (for task `ext_notif_receiver`: `contact_person`; for contact `company`: `client`). Invalid IDs return `400`. Look up client IDs with `client` `get_documents` / `get_document`.

**Response:**

```json
{
  "dvs_document_id": 4822
}
```

Use the returned `dvs_document_id` with `get_document` to retrieve the full record including auto-generated fields such as `full_number`.

---

### `update_document`

Updates an existing document. Only the fields provided in `update_params` are changed; all other fields keep their current values. Available for `task` and `contact_person`.

```text
POST https://api.files.fm/api_dvs/task/update_document
Content-Type: application/json
```

Auth: `user` and `user_access_token` in this JSON.

**Request:**

```json
{
  "user": "YOUR_USER",
  "user_access_token": "YOUR_API_TOKEN",
  "dvs_document_id": 4822,
  "update_params": {
    "dropdown_status": 14,
    "spent_hours": "2.5"
  }
}
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `dvs_document_id` | integer | Yes | ID of the document to update |
| `update_params` | object | Yes | Fields to change, keyed by field name |

The same field-level validation rules as `create_document` apply. The project (`dvs_project_id`) of a task cannot be changed through the API.

**Response:**

```json
{
  "dvs_document_id": 4822
}
```

---

### `add_comment`

Adds a comment on a task. Same storage and notifications as the DMS web interface (`htmlspecialchars` on save; HTML is shown in comment emails like task descriptions). Available for `task` only.

To mention a user, put `@[USER:user_id]` in the comment at the position you want (`USER` is the type prefix; `user_id` is the same integer `id` as in `get_users` / `get_document`). You can mention several users, including in the middle of a sentence. Plain `@name`, email addresses, and `@[1042]` without `USER:` stay as normal text. A mention id must belong to a user in the same organization. Mentions are not limited to project workers — the same as mentioning someone in the DMS web interface (they get the mention email even if they cannot open the task).

```text
POST https://api.files.fm/api_dvs/task/add_comment
Content-Type: application/json
```

Auth: `user` and `user_access_token` in this JSON.

**Request:**

```json
{
  "user": "YOUR_USER",
  "user_access_token": "YOUR_API_TOKEN",
  "dvs_document_id": 4821,
  "comment": "Please ask @[USER:1042] to review the draft before Friday."
}
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `dvs_document_id` | integer | Yes | ID of the task to comment on |
| `comment` | string | Yes | Comment body (same as the web editor). Must be non-empty after trimming. Insert `@[USER:user_id]` where a mention should appear. |

**Response:**

```json
{
  "dvs_document_id": 4821
}
```
