Appearance
Files
File management: listing, file properties and metadata, tags, removal, uploads, and workspace scoping.
A file is in one of two modes.
- Legacy (unscoped) - every file uploaded without a
workspaceId. Access is decided by reverse reference: you may read the file when something you can already see points at it (your profile picture, a workflow cover image, a feed post or comment, a discussion message, an activity). Nothing about these files changes. - Workspace-scoped - the file has a
workspaceId. Access is decided by its ACL alone: the owner (while a member of that workspace), a workspace admin or owner of that workspace, or a match inreaders(network_<workspaceId>,team_<teamId>,user_<userId>). A scoped file with no readers is visible to its owner and workspace admins only. Workspace guests have no access to scoped files:network_never matches them,user_cannot name them, ateam_grant skips them, and they cannot own one. A scoped file is never public.
Scope a file at upload (files.upload third argument, or the workspaceId form field of POST /upload) or afterwards with files.scope.set. Guests cannot scope files or use files.scope.*.
Scoping is strict and one-way. Once a file has a workspace, attaching it to an activity, discussion message or feed post no longer grants access to it: for people who can see the container but are not readers, the attachment is left out as if it were not there. The workspace can never be changed or removed.
Scoped file names are not in the activity search index, and links and search results leave out the scoped files you cannot read.
Endpoints
| Endpoint | Arguments | Returns |
|---|---|---|
files.get_file_properties | fileId: string | unknown |
files.list | fileIds: null | string | string[] | options: { workspaceId: string, search?: string | string[], matchType?: "all" | "any", skip?: number, limit?: number, sortBy?: "name" | "created", reverse?: boolean, scopedOnly?: boolean } | object |
files.my_files | - | object |
files.owner.set | fileId: string, owner: { uid: string } | boolean |
files.remove_files | unknown | boolean |
files.scope.get | fileId: string | object |
files.scope.set | fileId: string, scope: { workspaceId: string, readers?: string[] } | object |
files.set_file_metadata | file: { file_id: string }, metadata: { profilepic?: boolean } | unknown |
files.set_file_properties | properties: { _id: string, name?: string, profilepic?: boolean } | boolean |
files.tags.add | fileId, unknown, WorkspaceId | string[] |
files.tags.remove | fileId, unknown, WorkspaceId | string[] |
files.upload | content: Base64String | Buffer, filename: string, workspaceId?: string | object |
files.get_file_properties
Description
The stored document of a file you can read: a legacy file through something you can see that points at it, a workspace-scoped file as its owner (while a member), a workspace admin or a reader. A missing and an unreadable file both fail with Failed "Unable to get file properties.".
Parameters
Argument 1 (ObjectId, required):
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.get_file_properties', [
'507f1f77bcf86cd799439011', // ObjectId (required)
]);
console.log(result);Returns
Undocumented
The return value is not described in the source yet.
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.list
Description
List files, in one of two forms that return different item shapes.
Id form (null, a fileId or an array of fileIds): your own uploads (optionally narrowed to the given ids) as a map keyed by fileId. Own scoped files are included only while you are still a member of their workspace. Items are the raw stored files (cid, readers, hash).
Options form (an object with workspaceId): a paginated page { files, hasMore, total } of your own legacy (unscoped) files plus the workspace-scoped files of workspaceId that you can read: your own, those whose readers match you, or all of them for a workspace admin/owner. Legacy files have no workspace, so yours are listed for any workspaceId, including one where you are a guest or not a member; guests and non-members get only their own legacy files. With scopedOnly: true legacy files are left out and guests get PermissionDenied. Items carry workspaceId (absent for legacy files) and omit readers and hash. search is one keyword or an array of keywords (up to 20); a keyword matches a case-insensitive substring of the file name or of any tag. matchType combines them: all (default) requires every keyword to match, any at least one.
Parameters
Argument 1 (any \| fileId \| fileId[] \| object, optional):
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.list', [
'...', // argument 1
]);
console.log(result);Returns
Result form 1:
Record<string, any>
Result form 2:
| Field | Type | Required | Description |
|---|---|---|---|
files | object[] | yes | See below. |
hasMore | boolean | yes | |
total | number | yes |
files[] (object):
| Field | Type | Required | Description |
|---|---|---|---|
_id | ObjectId | no | |
hash | binary | no | |
uid | ObjectId | yes | |
length | number | no | |
name | string | no | |
created | timestamp | yes | Time (milliseconds since 1970-01-01 UTC) |
updated | timestamp | no | Time (milliseconds since 1970-01-01 UTC) |
removed | timestamp | no | Soft-delete timestamp; set when a DigiOne user deletes the file |
type | string | yes | MIME file type |
isPicture | boolean | no | |
isVideo | boolean | no | |
isPublic | boolean | no | |
fileSets | ObjectId[] | no | |
tags | string[] | no | |
cid | WorkspaceId | no | Workspace scope. Absent for legacy (unscoped) files; immutable once set |
readers | string[] | no | ACL of a workspace-scoped file |
dimensions | object | no | See below. |
workspaceId | WorkspaceId | no | workspaceId (former networkId) |
files[].dimensions (object):
| Field | Type | Required | Description |
|---|---|---|---|
height | number | no | |
width | number | no | |
aspectRatio | number | no |
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.my_files
Description
Your own uploads as a map keyed by fileId, leaving out removed files and those flagged profilepic. Your workspace-scoped files are included only while you are still a full member of their workspace. Items are the raw stored files, including cid and readers.
Parameters
Undocumented
This endpoint declares no argument schema in the source yet.
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.my_files', []);
console.log(result);Returns
Record<string, any>
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.owner.set
Description
Transfer a workspace-scoped file to another member of its workspace (not a guest). Workspace admins and owners only - the file's owner cannot transfer it themselves, and legacy (unscoped) files have no workspace to administer them. Setting the current owner is a no-op.
files.my_files, the id form of files.list and files.remove_files are owner-scoped, so the file moves to the new owner's lists and delete rights. The previous owner loses access unless they are matched by readers. Signals files.update { file_id } to the workspace.
Parameters
Argument 1 (fileId, required): fileId
Argument 2 (object, required):
| Field | Type | Required | Description |
|---|---|---|---|
uid | userId | yes | userId |
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.owner.set', [
'507f1f77bcf86cd799439011', // fileId (required)
{
uid: '507f1f77bcf86cd799439011', // userId
},
]);
console.log(result);Returns
boolean
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.remove_files
Description
Removes your own files. Ids of files you do not own are silently skipped, even for workspace admins, and your own workspace-scoped files are removed only while you are still a full member of their workspace. The records are deleted and the contents purged from storage; for DigiOne users the files are only flagged removed and kept. Signals files.remove { file_id: string[] } to the session workspace.
Parameters
Argument 1 (ObjectId[], optional):
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.remove_files', [
['507f1f77bcf86cd799439011'],
]);
console.log(result);Returns
boolean
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.scope.get
Description
Get the owner, workspace and readers of a file you can read. workspaceId (and readers) are absent for a legacy (unscoped) file, so this doubles as an "is this file scoped?" probe. Guests of the file's workspace cannot read its scoped files, so they get NotFound.
Parameters
Argument 1 (fileId, required): fileId
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.scope.get', [
'507f1f77bcf86cd799439011', // fileId (required)
]);
console.log(result);Returns
| Field | Type | Required | Description |
|---|---|---|---|
_id | fileId | yes | fileId |
uid | userId | yes | Owner of the file |
workspaceId | WorkspaceId | no | workspaceId (former networkId) |
readers | string[] | no |
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.scope.set
Description
Scope a file to a workspace and/or replace its readers. Not available to guests of workspaceId. On an unscoped file: the owner only, who must be a member of workspaceId; a public file cannot be scoped. On a scoped file: the owner (regardless of role, while still a member) or a workspace admin/owner; workspaceId must equal the file's current workspace, which never changes. readers replaces the stored list wholesale (omit to keep it; send [] to revoke all). Every entry must belong to workspaceId: network_ must be that workspace, team_ a team in it, user_ a member (not a guest) of it; only admins get the failing entries in details.invalid. A non-admin may only newly add teams they belong to; entries already stored are kept without re-checking. Signals files.update { file_id } to the workspace.
Scoping is strict and one-way. Once a file has a workspace, attaching it to an activity, discussion message or feed post no longer grants access to it: for people who can see the container but are not readers, the attachment is left out as if it were not there. The workspace can never be changed or removed.
Parameters
Argument 1 (fileId, required): fileId
Argument 2 (object, required):
| Field | Type | Required | Description |
|---|---|---|---|
workspaceId | WorkspaceId | yes | workspaceId (former networkId) |
readers | string[] | no |
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.scope.set', [
'507f1f77bcf86cd799439011', // fileId (required)
{
workspaceId: '507f1f77bcf86cd799439011', // workspaceId (former networkId)
},
]);
console.log(result);Returns
| Field | Type | Required | Description |
|---|---|---|---|
_id | fileId | yes | fileId |
uid | userId | yes | Owner of the file |
workspaceId | WorkspaceId | no | workspaceId (former networkId) |
readers | string[] | no |
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.set_file_metadata
Description
Sets the profilepic flag on one of your own files; true hides it from files.my_files and files.list. Files you do not own are silently left unchanged. On a workspace-scoped file you must still be a full member of its workspace, otherwise PermissionDenied.
Parameters
Argument 1 (object, optional):
| Field | Type | Required | Description |
|---|---|---|---|
file_id | ObjectId | yes |
Argument 2 (object, optional):
| Field | Type | Required | Description |
|---|---|---|---|
profilepic | boolean | no |
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.set_file_metadata', [
{
file_id: '507f1f77bcf86cd799439011',
},
{
profilepic: false,
},
]);
console.log(result);Returns
Undocumented
The return value is not described in the source yet.
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.set_file_properties
Description
Renames a file or sets its profilepic flag (true hides it from your file lists). fileSets, typeContent, isVideo, isPicture and isPublic are accepted but never written. Denied to guests of the session workspace. A legacy file can be changed by anyone who can read it, a workspace-scoped file only by its owner (while a member) or a workspace admin, otherwise PermissionDenied.
Parameters
Argument 1 (object, optional):
| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | |
fileSets | ObjectId[] | no | |
profilepic | boolean | no | |
typeContent | string | no | |
isVideo | boolean | no | |
isPicture | boolean | no | |
isPublic | boolean | no | |
_id | ObjectId | yes |
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.set_file_properties', [
{
_id: '507f1f77bcf86cd799439011',
},
]);
console.log(result);Returns
boolean
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.tags.add
Description
Adds one or more case-sensitive tags to a file. Duplicates against existing tags are ignored. A workspace-scoped file broadcasts files.update to its own workspace without tags.
Parameters
Argument 1 (fileId, required): File ID
Argument 2 (string[], required): Tags to add
Argument 3 (WorkspaceId, optional): Workspace (company) ID; when provided, scopes the guest check and the files.update broadcast
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.tags.add', [
'507f1f77bcf86cd799439011', // fileId (required)
['string'],
'507f1f77bcf86cd799439011', // WorkspaceId
]);
console.log(result);Returns
Array of string.
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.tags.remove
Description
Removes one or more tags from a file by case-sensitive exact match. Tags not present are silently ignored. A workspace-scoped file broadcasts files.update to its own workspace without tags.
Parameters
Argument 1 (fileId, required): File ID
Argument 2 (string[], required): Tags to remove
Argument 3 (WorkspaceId, optional): Workspace (company) ID; when provided, scopes the guest check and the files.update broadcast
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.tags.remove', [
'507f1f77bcf86cd799439011', // fileId (required)
['string'],
'507f1f77bcf86cd799439011', // WorkspaceId
]);
console.log(result);Returns
Array of string.
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.
files.upload
Description
Upload a file
Parameters
Argument 1 (object \| string, optional): content Binary or Base64String
Argument 2 (string, optional): name
Argument 3 (WorkspaceId, optional): workspaceId: scope the file to this workspace (owner + workspace admins only until readers are granted with files.scope.set); not for guests
Example
javascript
const { Client } = require('@hailer/cli');
const client = await Client.create({
host: 'https://api.hailer.com',
username: 'you@example.com',
password: '••••••',
});
const result = await client.request('files.upload', [
{ /* ... */ }, // content `Binary or Base64String`
'string', // name
'507f1f77bcf86cd799439011', // WorkspaceId
]);
console.log(result);Returns
| Field | Type | Required | Description |
|---|---|---|---|
_id | ObjectId | yes | fileId |
Auth: requires an authenticated session.
Errors: on failure returns the standard Hailer error object { code, msg, details?, retryAfter?, debug? }. retryAfter is a delay in milliseconds.