Skip to content

TrimbleCloud.FileService

The Trimble File Service provides capabilities for managing file type of resources organized into folders and related metadata in a secure way with predefined ACL roles.

This SDK is available as a NuGet package from Trimble Artifactory.

To install, use the following command:

dotnet add package TrimbleCloud.FileService

These are the US region endpoints for File Service:

Environment Base URL Endpoint
Stage https://cloud.stage.api.trimblecloud.com/fileservice/api/2.0
Production https://cloud.api.trimble.com/fileservice/api/2.0

For other regions, refer to the Trimble Cloud Console.

All Trimble Cloud .NET SDKs now use a standardized error handling approach based on the TrimbleServiceException class from the TrimbleCloud.FileService package. This provides consistent error information across all services.

The TrimbleServiceException is the primary exception class used across all Trimble Cloud SDKs. It provides detailed error information including:

  • HTTP Status Code - The HTTP status code of the failed request
  • Request ID - A unique identifier for tracking and support purposes
  • Error Details - Structured error information from the service
  • Raw Response - Access to the original HTTP response for advanced debugging
try
{
var file = await fileServiceClient.Files.Get(spaceId, fileId);
Console.WriteLine($"Retrieved file: {file.Data.Name}");
}
catch (TrimbleServiceException ex)
{
Console.WriteLine($"Service error: {ex.Message}");
Console.WriteLine($"Status Code: {ex.StatusCode}");
Console.WriteLine($"Request ID: {ex.RequestId}");
// Serilazable
Console.WriteLine(JsonConvert.SerializeObject(ex, Formatting.Indented));
}

Service request failed. Status: <STATUS_CODE> <STATUS_MESSAGE> RequestId: <REQUEST_ID> Response Content: <API_ERROR_RESPONSE_BODY>

To create a FileServiceClient, you need to provide a token provider and the File Service endpoint. The token provider is used to authenticate the client with Trimble Identity (TID).

using Trimble.ID;
using TrimbleCloud.FileService;
//Setup a TID provider for communications with our authorization server TID
var endpointProvider = new OpenIdEndpointProvider(new Uri("<CONFIG_ENDPOINT>", UriKind.Absolute));
//Setup a token provider to handle the token exchange with TID
var tokenProvider = new ClientCredentialTokenProvider(endpointProvider, "<CLIENT_ID>", "<CLIENT_SECRET>").WithScopes("<SCOPES>");
var client = new FileServiceClient(new BearerTokenHttpClientProvider(tokenProvider, new Uri("<FILE_SERVICE_ENDPOINT>")));

Refer to the Trimble ID SDK documentation for more information on setting up the token provider.

The FileServiceClient uses a default configuration for retries and timeouts. It is used to handle transient failures and network issues. The following properties can be configured:

  • Retries - The number of retries for the client. Default is 3.
  • RetryInterval - The retry interval for the client. Default is 5 seconds. We have an exponential backoff strategy for retries which doubles the interval after each retry.
  • HttpTimeout - The timeout for the client. Default is 5 minutes.

To create FileServiceClient with custom configurations, you can use the FileServiceClientConfig class.

var config = new FileServiceClientConfig();
// Set the number of retries for the client
config.Retries = 5;
// Set the retry interval for the client
config.RetryInterval = TimeSpan.FromSeconds(10);
// Set the timeout for the client
config.HttpTimeout = TimeSpan.FromMinutes(6);
var client = new FileServiceClient(new BearerTokenHttpClientProvider(tokenProvider, new Uri("<FILE_SERVICE_ENDPOINT>")), config);
  • The minimal response feature provides a streamlined version of response data by including only essential attributes of an entity.
  • This reduces the response size, leading to faster data transfer and lower bandwidth usage.
  • It is particularly useful when the client does not need all the attributes of an entity.
  • The minimal response feature is applicable for all synchronous operation responses, including methods such as Create, Get, Update, Move, Rename, Restore, Lock, Unlock, GetVersion, and List methods.
  • A space is a container for files and folders.
  • It is the top-level entity in the file service.
  • A root folder is created automatically when a space is created.

Create a new space.

var aclList = new List<Acl>()
{
new Acl() { Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")), Role = AclRole.SpaceManager },
new Acl() { Actor = new AclDeviceIdentity(Guid.Parse("<DEVICE_ID>")), Role = AclRole.ContentManager, AccessExpiresAt = DateTime.UtcNow.AddDays(30) },
new Acl() { Actor = new AclUserIdentity(Guid.Parse("<USER_ID>")), Role = AclRole.ContentContributor }
};
// `SpaceMembershipBoundary` allow restrict content access to space members in which `group` is the IAM group identifier and `allowLimitedViewerOutsideBoundaryGroup` if true, users outside the space membership boundary group can be granted limited viewer access.
Response<Space> space = await client.Spaces.Create(new SpaceCreate()
{
Name = "<SPACE_NAME>",
AccountId = "<ACCOUNT_ID>",
PermissionsLocal = new SpacePermissionsLocal()
{
Acl = aclList
},
Provider = Provider.AWS,
SoftDeleteRetention = RetentionPeriod.OneYear,
SpaceMembershipBoundary = new SpaceMembershipBoundary()
{
Group = "<GROUP_TRN>",
AllowLimitedViewerOutsideBoundaryGroup = true
},
AllowAnonymousShares = true
});
// To create a space with anonymous access, you must enable AllowAnonymousShares
// and add an AclCustomIdentity("anonymous") with LimitedViewer role
var aclListWithAnonymous = new List<Acl>()
{
new Acl() { Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")), Role = AclRole.SpaceManager },
new Acl() { Actor = new AclCustomIdentity("anonymous"), Role = AclRole.LimitedViewer },
// Group "trn:2:iam:us:group:<GROUP_ID>" can be added as an actor only if space has membership boundary
new Acl() { Actor = new AclCustomIdentity("trn:2:iam:us:group:<GROUP_ID>"), Role = AclRole.LimitedViewer }
};
Response<Space> anonymousSpace = await client.Spaces.Create(new SpaceCreate()
{
Name = "<SPACE_NAME>",
AccountId = "<ACCOUNT_ID>",
PermissionsLocal = new SpacePermissionsLocal()
{
Acl = aclListWithAnonymous
},
Provider = Provider.AWS,
AllowAnonymousShares = true
});

To create a space and get a minimal response, use the CreateWithMinimalResponse method.

Response<MinimalSpace> space = await client.Spaces.CreateWithMinimalResponse(new SpaceCreate()
{
Name = "<SPACE_NAME>",
AccountId = "<ACCOUNT_ID>",
SpaceMembershipBoundary = new SpaceMembershipBoundary()
{
Group = "<GROUP_TRN>",
AllowLimitedViewerOutsideBoundaryGroup = true
},
AllowAnonymousShares = false
});

Get space by ID.

Response<Space> space = await client.Spaces.Get(spaceId);

The optional status parameter can be used to filter the spaces based on the status.

Response<Space> space = await client.Spaces.Get(spaceId, status: ResourceStatus.Active);

To get a space with minimal response, use the GetWithMinimalResponse method.

Response<MinimalSpace> space = await client.Spaces.GetWithMinimalResponse(spaceId, status: ResourceStatus.Active);

Update space by ID. Only the name, ACL details, soft delete retention, space membership boundary, and anonymous shares setting can be updated for a space.

SpaceMembershipBoundaryis space membership boundary settings that allow space managers to restrict content access to space members in which group is the IAM group identifier that defines the space membership boundary and allowLimitedViewerOutsideBoundaryGroupWhen true, users outside the space membership boundary group can be granted limited viewer access. When false, only members of the space membership boundary group are permitted to access content.

// Here, the existing permissions are replaced with the new ACL list.
Response<Space> space = await client.Spaces.Update(spaceId, new SpaceUpdate()
{
Name = "<NEW_NAME>",
PermissionsLocal = new SpaceUpdatePermissionsLocal()
{
ReplaceAcl = new List<Acl>()
{
new Acl() { Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")), Role = AclRole.ContentManager, AccessExpiresAt = DateTime.UtcNow.AddDays(30) },
new Acl() { Actor = new AclUserIdentity(Guid.Parse("<USER_ID>")), Role = AclRole.ContentContributor }
}
},
SoftDeleteRetention = RetentionPeriod.OneYear,
SpaceMembershipBoundary = new SpaceMembershipBoundary()
{
Group = "<GROUP_TRN>",
AllowLimitedViewerOutsideBoundaryGroup = false
},
AllowAnonymousShares = true
});
// To add or remove permissions, use the UpdateAcl field.
Response<Space> space = await client.Spaces.Update(spaceId, new SpaceUpdate()
{
Name = "<NEW_NAME>",
PermissionsLocal = new SpaceUpdatePermissionsLocal()
{
UpdateAcl = new SpaceUpdateAcl
{
Add = new List<Acl>()
{
new Acl() { Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")), Role = AclRole.ContentContributor, AccessExpiresAt = DateTime.UtcNow.AddDays(15) },
},
Remove = new List<Acl>()
{
new Acl() { Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")), Role = AclRole.ContentManager },
}
}
},
SoftDeleteRetention = RetentionPeriod.OneYear,
SpaceMembershipBoundary = new SpaceMembershipBoundary()
{
Group = "<GROUP_TRN>",
AllowLimitedViewerOutsideBoundaryGroup = true
},
AllowAnonymousShares = false
});

To update a space and get a minimal response, use the UpdateWithMinimalResponse method.

Response<MinimalSpace> space = await client.Spaces.UpdateWithMinimalResponse(spaceId, new SpaceUpdate()
{
Name = "<NEW_NAME>"
});

Delete space by ID. By default, it is a non-recursive soft delete operation.

Empty space deletion will not return any job ID. Non-empty space deletion is an asynchronous operation which returns the job ID.

await client.Spaces.Delete(spaceId);

The optional recursive parameter can be used to delete the space and its contents recursively. The permanent parameter can be used to delete the space permanently.

Guid? jobId = await client.Spaces.Delete(spaceId, recursive: true, permanent: true);

NOTE: A non-empty space can only be deleted with recursive parameter set to true.

The restore space operation is used to restore a deleted space within 30 days of its deletion. Any resources nested under the restored space or folder will be restored through an asynchronous process.

(Response<Space> Space, Guid? JobId) result = await client.Spaces.Restore(spaceId);

To restore a space and get a minimal response, use the RestoreWithMinimalResponse method.

(Response<MinimalSpace> Space, Guid? JobId) result = await client.Spaces.RestoreWithMinimalResponse(spaceId);

List spaces that the user has access to.

NOTE: The ListChildren method returns a minimal response by default, and there is no option to retrieve a full response.

string nextPageToken = "";
do
{
var response = await client.Spaces.ListChildren(spaceId, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page (default is 100, max is 1000).

var response = await client.Spaces.ListChildren(spaceId, maxItems: 50);

You can also use the includeSupportFiles parameter to include support files in the response, and provide a SpaceListFilterCriteria for filtering the results.

var listFilter = new SpaceListFilterCriteria { Status = ResourceStatus.All };
var response = await client.Spaces.ListChildren(spaceId, maxItems: 50, includeSupportFiles: true, listFilter: listFilter);

You can filter by resource type to retrieve only files or only folders:

// Filter to show only files
var listFilter = new SpaceListFilterCriteria { ResourceType = "FILE" };
var response = await client.Spaces.ListChildren(spaceId, listFilter: listFilter);

Additionally, you can specify the sort order using the sortOrder parameter:

// Sort by name in ascending order
var response = await client.Spaces.ListChildren(spaceId, sortOrder: "asc");
// Sort by created date in descending order
var response = await client.Spaces.ListChildren(spaceId, sortOrder: "desc");
  • A folder is a container for files and other folders.

Create a new folder.

Response<Folder> folder = await client.Folders.Create(spaceId, new FolderCreate()
{
Name = "<FOLDER_NAME>",
ParentId = parentId
});

NOTE: To create a folder under the root folder of a space, set the ParentId as the RootId of the space.

To create a folder and get a minimal response, use the CreateWithMinimalResponse method.

Response<MinimalFolder> folder = await client.Folders.CreateWithMinimalResponse(spaceId, new FolderCreate()
{
Name = "<FOLDER_NAME>",
ParentId = parentId
});

Create multiple folders with a hierarchical structure in a single API call. This is useful for creating complex folder structures efficiently.

var batchRequest = new BatchFolderCreate
{
Folders = new List<FolderCreateWithChildren>
{
new FolderCreateWithChildren
{
ParentId = new Guid("<PARENT_ID>"),
Name = "<PARENT_FOLDER1>",
Children = new List<FolderCreateChild>
{
new FolderCreateChild
{
Name = "<CHILD_FOLDER1>"
},
new FolderCreateChild
{
Name = "<CHILD_FOLDER2>",
Children = new List<FolderCreateChild>
{
new FolderCreateChild
{
Name = "<GRAND_CHILD_FOLDER1>"
}
}
}
}
},
new FolderCreateWithChildren
{
ParentId = new Guid("<PARENT_ID>"),
Name = "<PARENT_FOLDER2>"
}
}
};
Response<BatchFolderList> response = await client.Folders.CreateBatch(new Guid("<SPACE_ID>"), batchRequest);

To create batch folders and get a minimal response, use the CreateBatchWithMinimalResponse method.

Response<BatchMinimalFolderList> response = await client.Folders.CreateBatchWithMinimalResponse(new Guid("<SPACE_ID>"), batchRequest);

The response contains two lists:

  • Items: Successfully created folders
  • InvalidItems: Folders that could not be created, with error details

Get folder by ID.

Response<Folder> folder = await client.Folders.Get(spaceId, folderId);

The optional status parameter can be used to filter the folders based on the status.

Response<Folder> folder = await client.Folders.Get(spaceId, folderId, status: ResourceStatus.All);

To get a folder with minimal response, use the GetWithMinimalResponse method.

Response<MinimalFolder> folder = await client.Folders.GetWithMinimalResponse(spaceId, folderId, status: ResourceStatus.All);

Get folder by path.

Response<Folder> folder = await client.Folders.Get(spaceId, "<FOLDER_PATH>");

The optional status parameter can be used to filter the folders based on the status.

Response<Folder> folder = await client.Folders.Get(spaceId, "<FOLDER_PATH>", status: ResourceStatus.All);

To get a folder with minimal response, use the GetWithMinimalResponse method.

Response<MinimalFolder> folder = await client.Folders.GetWithMinimalResponse(spaceId, "<FOLDER_PATH>", status: ResourceStatus.All);

Update folder by ID. Only the metadata and ACL settings can be updated.

Response<Folder> folder = await client.Folders.Update(spaceId, folderId, new FolderUpdate()
{
Metadata = new Dictionary<string, object>
{
{ "key1", "value1" },
{ "key2", "value2" }
}
});

You can also include headers in the request

Response<Folder> folder = await client.Folders.Update(spaceId, folderId, new FolderUpdate()
{
Metadata = new Dictionary<string, object>
{
{ "key1", "value1" },
{ "key2", "value2" }
},
new Dictionary<string, string>()
{
{ "If-Match", "2" }
}
});

To update a folder and get a minimal response, use the UpdateWithMinimalResponse method. You can also include headers in the request.

Response<MinimalFolder> folder = await client.Folders.UpdateWithMinimalResponse(spaceId, folderId, new FolderUpdate()
{
Metadata = new Dictionary<string, object>
{
{ "key1", "value1" }
}
});

Delete folder by ID. By default, it is a non-recursive soft delete operation.

Empty folder deletion will not return any job ID. Non-empty folder deletion is an asynchronous operation which returns the job ID.

await client.Folders.Delete(spaceId, folderId);

The optional recursive parameter can be used to delete the folder and its contents recursively. The permanent parameter can be used to delete the folder permanently. You can also include headers in the request.

Guid? jobId = await client.Folders.Delete(spaceId, folderId, headers: new Dictionary<string, string>()
{
{ "If-Match", "2" }
}, recursive: true, permanent: true);

NOTE: A non-empty folder can only be deleted with recursive parameter set to true.

Move a folder to a new location within the same space.

(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Move(spaceId, folderId, targetParentId);

The optional name parameter can be used to specify a new name for the moved folder. You can also include headers in the request.

(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Move(spaceId, folderId, targetParentId, new Dictionary<string, string>()
{
{ "<HEADER>", "<VALUE>" }
}, <NEW_NAME>);

To move a folder and get a minimal response, use the MoveWithMinimalResponse method. (The optional name parameter can be used to specify a new name for the moved folder. You can also include headers in the request.)

(Response<MinimalFolder> Folder, Guid? JobId) result = await client.Folders.MoveWithMinimalResponse(spaceId, folderId, targetParentId);

Rename a folder with a new name. The folder will be renamed to the target name and the folder ID will remain the same.

(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Rename(spaceId, folderId, "<NEW_FOLDER_NAME>");

You can also include headers in the request

(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Rename(spaceId, folderId, "<NEW_FOLDER_NAME>", , new Dictionary<string, string>()
{
{ "<HEADER>", "<VALUE>" }
});

To rename a folder and get a minimal response, use the RenameWithMinimalResponse method.(You can also include headers in the request)

(Response<MinimalFolder> Folder, Guid? JobId) result = await client.Folders.RenameWithMinimalResponse(spaceId, folderId, "<NEW_FOLDER_NAME>");

Copy a folder to a new location within the same space. The folder will be copied to the target location and a new folder ID will be generated.

(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Copy(spaceId, folderId, targetParentId);

The optional name parameter can be used to specify a new name for the copied folder. The optional includeSupportFiles parameter, if true, copies the support files along with the files in the folder and creates links between the copied main file and the copied support files. The overwriteExisting query parameter, if specified and true, determines whether to overwrite an existing resource by creating a new version with the copied content.

(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Copy(spaceId, folderId, targetParentId, name: "<NEW_FOLDER_NAME>", includeSupportFiles: true, overwriteExisting: true);

You can also use the CopyFolderRequest class to provide all parameters for copying a file, including specifying a version to copy:

CopyFolderRequest copyFolderRequest = new CopyFolderRequest()
{
SpaceId = new Guid("<SPACE_ID>"),
FolderId = new Guid("<FOLDER_ID>"),
TargetParentId = new Guid("<TARGET_PARENT_ID>"),
Headers = new Dictionary<string, string>()
{
{"<HEADER>", "<VALUE>" }
},
PermissionsLocal = new FolderUpdatePermissionsLocal()
{
Acl = new List<Acl>()
{
new Acl() { Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")), Role = AclRole.ContentContributor },
new Acl() { Actor = new AclUserIdentity(Guid.Parse("<USER_ID>")), Role = AclRole.ContentViewer }
}
},
CopyAcl = false
};
(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Copy(copyFolderRequest);

To copy a folder and get a minimal response, use the CopyWithMinimalResponse method.

(Response<MinimalFolder> Folder, Guid? JobId) result = await client.Folders.CopyWithMinimalResponse(spaceId, folderId, targetParentId);

You can also use the CopyFolderRequest class with the minimal response version:

(Response<MinimalFolder> Folder, Guid? JobId) result = await client.Folders.CopyWithMinimalResponse(copyFolderRequest);

Restore a folder and it’s children from the deleted state. By default, the folder will be restored to its original location.

(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Restore(spaceId, folderId);

The optional name parameter can be used to specify a new name for the restored folder and the targetParentId parameter can be used to restore the folder to a new location. You can also include headers in the request.

(Response<Folder> Folder, Guid? JobId) result = await client.Folders.Restore(spaceId, folderId, "<NEW_FOLDER_NAME>", targetParentId, , new Dictionary<string, string>()
{
{ "<HEADER>", "<VALUE>" }
});

To restore a folder and get a minimal response, use the RestoreWithMinimalResponse method. You can also include headers in the request.

(Response<MinimalFolder> Folder, Guid? JobId) result = await client.Folders.RestoreWithMinimalResponse(spaceId, folderId);

Get list of the folder children by ID.

NOTE: The ListChildren method returns a minimal response by default, and there is no option to retrieve a full response.

string nextPageToken = "";
do
{
var response = await client.Folders.ListChildren(spaceId, folderId, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page, the listFilter parameter can be used to filter the list of children, the sortBy parameter can be used to sort the list of children by name, size etc., the sortOrder parameter can be used to specify the sort order (asc or desc) and the recursive retrieves all children of the folder recursively, if true. These methods are deprecated.

string nextPageToken = "";
do
{
var listFilterCriteria = new ListFilterCriteria { Status = ResourceStatus.All, UrlDuration = TimeSpan.FromMinutes(300) };
var response = await client.Folders.ListChildren(spaceId, folderId, nextPageToken, maxItems: 50, listFilter: listFilterCriteria, sortBy: sortByField, sortOrder: asc, recursive: true);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

NOTE: The legacy methods use ListFilterCriteria which does not support filtering by resource type. Use FolderListChildrenRequest with FolderListFilterCriteria for full functionality including resource type filtering.

var request = new FolderListChildrenRequest
{
SpaceId = spaceId,
FolderId = folderId,
// alternatively path = <FOLDER_PATH> can be used
FilterCriteria = new FolderListFilterCriteria
{
Status = ResourceStatus.Active,
ResourceType = "FILE" // Filter by resource type: "FILE" or "FOLDER"
},
MaxItems = 50,
SortBy = "name",
SortOrder = "asc",
Recursive = true
};
var response = await client.Folders.ListChildren(request);

Get list of the folder children by path.

NOTE: The ListChildren method returns a minimal response by default, and there is no option to retrieve a full response.

do
{
var response = await client.Folders.ListChildren(spaceId, path, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page and the listFilter parameter can be used to filter the list of children. This method is deprecated.

do
{
var listFilterCriteria = new ListFilterCriteria { Status = ResourceStatus.All, UrlDuration = TimeSpan.FromMinutes(300) };
var response = await client.Folders.ListChildren(spaceId, path, nextPageToken, maxItems: 50, listFilter: listFilterCriteria);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

Get details for the specified folder version by ID.

Response<Folder> folder = await client.Folders.GetVersion(spaceId, folderId, versionId: 1);

NOTE: The version identifier will be a whole number for folders.

The optional status parameter can be used to filter the folder versions based on the status.

Response<Folder> folder = await client.Folders.GetVersion(spaceId, folderId, versionId: 1, status: ResourceStatus.All);

To get a folder version with minimal response, use the GetVersionWithMinimalResponse method.

Response<MinimalFolder> folder = await client.Folders.GetVersionWithMinimalResponse(spaceId, folderId, versionId: 1, status: ResourceStatus.All);

Get details for the specified folder version by path.

Response<Folder> folder = await client.Folders.GetVersion(spaceId, "<FOLDER_PATH>", versionId: 1);

The optional status parameter can be used to filter the folder versions based on the status.

Response<Folder> folder = await client.Folders.GetVersion(spaceId, "<FOLDER_PATH>", versionId: 1, status: ResourceStatus.All);

To get a folder version with minimal response, use the GetVersionWithMinimalResponse method.

Response<MinimalFolder> folder = await client.Folders.GetVersionWithMinimalResponse(spaceId, "<FOLDER_PATH>", versionId: 1, status: ResourceStatus.All);

Get list of the folder versions by ID.

do
{
var response = await client.Folders.ListVersions(spaceId, folderId, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page and the status parameter can be used to filter the folder versions based on the status.

do
{
var response = await client.Folders.ListVersions(spaceId, folderId, nextPageToken, maxItems: 10, status: ResourceStatus.All);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

To get the folder versions with minimal response, use the ListVersionsWithMinimalResponse method.

do
{
var response = await client.Folders.ListVersionsWithMinimalResponse(spaceId, folderId, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

Get list of the folder versions by path.

do
{
var response = await client.Folders.ListVersions(spaceId, path, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page and the status parameter can be used to filter the folder versions based on the status.

do
{
var response = await client.Folders.ListVersions(spaceId, path, nextPageToken, maxItems: 20, status: ResourceStatus.All);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

To get the folder versions with minimal response, use the ListVersionsWithMinimalResponse method.

do
{
var response = await client.Folders.ListVersionsWithMinimalResponse(spaceId, path, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

Check out a folder within a space. Checking out a folder will lock it and prevent other users from making changes while you are working on it.

Response<Folder> folder = await client.Folders.CheckOutFolder(spaceId, folderId, "Reason for check out");

You can also include headers in the request

Response<Folder> folder = await client.Folders.CheckOutFolder(spaceId, folderId, "Reason for check out", new Dictionary<string, string>()
{
{ "<HEADER1>", "VALUE1" }
});

To check out a folder and get a minimal response, use the CheckOutFolderWithMinimalResponse method.

Response<MinimalFolder> folder = await client.Folders.CheckOutFolderWithMinimalResponse(spaceId, folderId, "Reason for check out");

Check in a folder that was previously checked out. This will unlock the folder and make it available for other users to modify.

Response<Folder> folder = await client.Folders.CheckInFolder(spaceId, folderId);

To check in a folder and get a minimal response, use the CheckInFolderWithMinimalResponse method.

Response<MinimalFolder> folder = await client.Folders.CheckInFolderWithMinimalResponse(spaceId, folderId);
  • A file is a binary object that resides under a folder.

Get file by ID.

Response<File> file = await client.Files.Get(spaceId, fileId);

The optional status parameter can be used to filter the files based on the status, the urlDuration parameter can be used to specify the download URL validity duration and the responseContentType parameter can be used to specify the content type of the response. The default value for urlDuration is 1 hour.

Response<File> file = await client.Files.Get(spaceId, fileId, status: ResourceStatus.All, urlDuration: TimeSpan.FromMinutes(300), responseContentType = "application/json");

To get a file with minimal response, use the GetWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.GetWithMinimalResponse(spaceId, fileId, status: ResourceStatus.All);

Get file by path.

Response<File> file = await client.Files.Get(spaceId, "<FILE_PATH>");

The optional status parameter can be used to filter the files based on the status, the urlDuration parameter can be used to specify the download URL validity duration and the responseContentType parameter can be used to specify the content type of the response. The default value for urlDuration is 1 hour.

Response<File> file = await client.Files.Get(spaceId, "<FILE_PATH>", status: ResourceStatus.All, urlDuration: TimeSpan.FromMinutes(300), responseContentType: "application/json");

To get a file with minimal response, use the GetWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.GetWithMinimalResponse(spaceId, "<FILE_PATH>", status: ResourceStatus.All);

Generates a pre-signed upload url for the given name and parent ID. The returned upload ID is used to upload the file.

If Multipart is set to true, the file will be uploaded in parts and it is handled by the SDK.

Response<UploadDetails> upload = await client.Files.CreateFileUpload(spaceId, new FileUploadCreate
{
Name = "<FILE_NAME>",
ParentId = parentId,
Multipart = true
});

You can set file permissions during creation using either the new FileAcl property with version support or the deprecated Acl property for backward compatibility.

Using the new FileAcl with version support:

Response<UploadDetails> upload = await client.Files.CreateFileUpload(spaceId, new FileUploadCreate
{
Name = "<FILE_NAME>",
ParentId = parentId,
PermissionsLocal = new FilePermissionsLocal()
{
Inherits = false,
FileAcl = new List<FileAcl>()
{
new FileAcl()
{
Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")),
Role = AclRole.ContentViewer,
Versions = new List<string>() { "1", "2" }, // Access only to versions 1 and 2
AccessExpiresAt = DateTime.UtcNow.AddDays(30)
},
new FileAcl()
{
Actor = new AclCustomIdentity("anonymous"),
Role = AclRole.LimitedViewer,
AccessExpiresAt = DateTime.UtcNow.AddDays(7)
}
}
}
});

Using the deprecated Acl property for backward compatibility:

Response<UploadDetails> upload = await client.Files.CreateFileUpload(spaceId, new FileUploadCreate
{
Name = "<FILE_NAME>",
ParentId = parentId,
PermissionsLocal = new FilePermissionsLocal()
{
Inherits = true,
Acl = new List<Acl>()
{
new Acl()
{
Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")),
Role = AclRole.SupportFileAdmin,
AccessExpiresAt = DateTime.UtcNow.AddDays(30)
}
}
}
});

The optional urlDuration parameter can be used to specify the upload URL validity duration and the includeLinks parameter can be used to specify whether to include the links from the last version during a file’s major version change. The default value for urlDuration is 1 hour. You can also include headers in the request.

Response<UploadDetails> upload = await client.Files.CreateFileUpload(spaceId, new FileUploadCreate
{
Name = "<FILE_NAME>",
ParentId = parentId,
Multipart = true,
},
new Dictionary<string, string>()
{
{ "If-Match", "1.*" }
},
urlDuration: TimeSpan.FromMinutes(300), includeLinks: true);

Generates a pre-signed upload url for the given name and parent ID (parent should be file for support files). The returned upload ID is used to upload the support file.

Response<UploadDetails> upload = await client.Files.CreateFileUpload(spaceId, new SupportFileUploadCreate
{
Name = "<SUPPORT_FILE_NAME>",
ParentId = parentId
});

The optional urlDuration parameter can be used to specify the upload URL validity duration. The default value for urlDuration is 1 hour. You can also include headers in the request.

Response<UploadDetails> upload = await client.Files.CreateFileUpload(spaceId, new SupportFileUploadCreate
{
Name = "<SUPPORT_FILE_NAME>",
ParentId = parentId
},
new Dictionary<string, string>()
{
{ "If-Match", "*" }
},
urlDuration: TimeSpan.FromMinutes(300));

Package upload allows for the simultaneous uploading of a main file along with its associated support files. A maximum of 10 support files can be included in the package upload and by default, the support file are linked to the main file.

var resources = new List<SupportFileResource>()
{
new SupportFileResource() { Name = "<SUPPORT_FILE_NAME>", SupportFileKey = "<SUPPORT_FILE_KEY>" },
new SupportFileResource() { Name = "<SUPPORT_FILE_NAME>" }
};
var packageUploadCreate = new PackageUploadCreate()
{
Name = "<FILE_NAME>",
ParentId = parentId,
SupportFileResources = resources
};
Response<UploadDetails> upload = await client.Files.CreatePackageUpload(spaceId, packageUploadCreate);

You can also include headers in the request:

Response<UploadDetails> upload = await client.Files.CreatePackageUpload(spaceId, packageUploadCreate,
new Dictionary<string, string>()
{
{ "<HEADER>", "<VAALUE>" }
},
urlDuration: TimeSpan.FromMinutes(300));

Retrieve the upload details by ID.

Response<UploadDetails> upload = await client.Files.GetUploadDetails(spaceId, uploadId);

The optional urlDuration parameter can be used to specify the upload URL validity duration.

Response<UploadDetails> upload = await client.Files.GetUploadDetails(spaceId, uploadId, urlDuration: TimeSpan.FromMinutes(300));

The optional parameters can be added using GetUploadDetailsQueryParams

Response<UploadDetails> upload = await client.Files.GetUploadDetails(spaceId, uploadId, new GetUploadDetailsQueryParams(){
LongPoll = false,
FastCheck = false
});

Important Note: Calling GetUploadDetails generates a new upload URL with the specified urlDuration. If you previously created an upload with a custom URL duration (e.g., via CreateFileUpload), calling GetUploadDetails will reset the URL expiry to the new duration specified (or the default 60 minutes if not specified). To avoid this, use the Upload(UploadDetails, Stream) method with pre-fetched upload details.

Link support files to a specific version of a file. The support files will be linked to the target main file and the main file’s minor version will be incremented.

var links = new Dictionary<string, SupportFileLink>() {
{"<KEY>", new SupportFileLink() { Id = new Guid("<SUPPORT_FILE_ID>") } },
{"<KEY>", new SupportFileLink() { Id = new Guid("<SUPPORT_FILE_ID>"), Version = "<VERSION>"} }
};
Response<File> file = await client.Files.CreateOrUpdateLinks(new Guid("<SPACE_ID>"), new Guid("<FILE_ID>"), fileMajorVersion: 1, links: links);

To create or update links and get a minimal response, use the CreateOrUpdateLinksWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.CreateOrUpdateLinksWithMinimalResponse(new Guid("<SPACE_ID>"), new Guid("<FILE_ID>"), fileMajorVersion: 1, links: links);

Upload a file to an existing upload using upload ID and upload URL.

The chunk size in bytes and the maximum number of concurrent requests can be specified. The default chunk size is 15 MB and the default max concurrent requests is 8.

The optional UrlDuration property specifies the upload URL validity duration when calling GetUploadDetails internally. If not specified, defaults to 60 minutes (or 2 days for files larger than 10GB).

using (var stream = System.IO.File.OpenRead("<FILE_PATH>"))
{
UploadRequest uploadRequest = new UploadRequest
{
SpaceId = new Guid("<SPACE_ID>"),
UploadId = new Guid("<UPLOAD_ID>"),
Stream = stream,
UrlDuration = TimeSpan.FromHours(5) // Optional
};
await client.Files.Upload(uploadRequest, chunkSize: 50 * 1024 * 1024, maxConcurrentRequests: 4);
}

Upload a file using the UploadDetails response from CreateFileUpload or GetUploadDetails.

This method uses the existing URL and urlDuration in the uploadDetails

// Using response from CreateFileUpload or GetUploadDetails
using (var stream = System.IO.File.OpenRead("<FILE_PATH>"))
{
await client.Files.Upload(uploadDetails, stream, chunkSize: 50 * 1024 * 1024, maxConcurrentRequests: 4);
}

Upload a file along with support files to the given package upload ID.

Maximum of 10 support files can be included in the package upload. The support files will be linked to the main file by default.

The optional UrlDuration property specifies the upload URL validity duration when calling GetUploadDetails internally.

using (var mainStream = System.IO.File.OpenRead("<FILE_PATH>"))
using (var supportStream1 = System.IO.File.OpenRead("<SUPPORT_FILE_PATH>"))
using (var supportStream2 = System.IO.File.OpenRead("<SUPPORT_FILE_PATH>"))
{
var supportFiles = new List<SupportFileResourceUploadItem>()
{
new SupportFileResourceUploadItem() { SupportFileKey = "<SUPPORT_FILE_KEY>", SupportFileStream = supportStream1},
new SupportFileResourceUploadItem() { SupportFileKey = "<SUPPORT_FILE_KEY>", SupportFileStream = supportStream2}
};
PackageUploadRequest uploadRequest = new PackageUploadRequest
{
SpaceId = new Guid("<SPACE_ID>"),
UploadId = new Guid("<UPLOAD_ID>"),
MainFileStream = mainStream,
SupportFiles = supportFiles,
UrlDuration = TimeSpan.FromHours(5) // Optional
};
await client.Files.Upload(uploadRequest, chunkSize: 50 * 1024 * 1024, maxConcurrentRequests: 4);
}

Upload a package using the UploadDetails response from CreatePackageUpload or GetUploadDetails.

// Using response from CreatePackageUpload or GetUploadDetails
using (var mainStream = System.IO.File.OpenRead("<FILE_PATH>"))
using (var supportStream1 = System.IO.File.OpenRead("<SUPPORT_FILE_PATH>"))
{
var supportFiles = new List<SupportFileResourceUploadItem>()
{
new SupportFileResourceUploadItem() { SupportFileKey = "<SUPPORT_FILE_KEY>", SupportFileStream = supportStream1}
};
await client.Files.Upload(uploadDetails, mainStream, supportFiles, chunkSize: 50 * 1024 * 1024, maxConcurrentRequests: 4);
}

Download a file by ID.

The chunk size in bytes and the maximum number of concurrent requests can be specified. The default chunk size is 15 MB and the default max concurrent requests is 8.

using (var stream = System.IO.File.OpenWrite("<FILE_NAME>"))
{
await client.Files.Download(spaceId, fileId, stream, chunkSize: 50 * 1024 * 1024, maxConcurrentRequests: 4);
}

The optional urlDuration parameter can be used to specify the download URL validity duration.

using (var stream = System.IO.File.OpenWrite("<FILE_NAME>"))
{
await client.Files.Download(spaceId, fileId, stream, urlDuration: TimeSpan.FromHours(2), chunkSize: 50 * 1024 * 1024, maxConcurrentRequests: 4);
}

Download a file by path.

The chunk size in bytes and the maximum number of concurrent requests can be specified. The default chunk size is 15 MB and the default max concurrent requests is 8.

using (var stream = System.IO.File.OpenWrite("<FILE_NAME>"))
{
await client.Files.Download(spaceId, path, stream, chunkSize: 50 * 1024 * 1024, maxConcurrentRequests: 4);
}

The optional urlDuration parameter can be used to specify the download URL validity duration.

using (var stream = System.IO.File.OpenWrite("<FILE_NAME>"))
{
await client.Files.Download(spaceId, path, stream, urlDuration: TimeSpan.FromHours(2), chunkSize: 50 * 1024 * 1024, maxConcurrentRequests: 4);
}

Complete the multipart upload for the given upload ID.

List<FilePart> partsList = new List<FilePart> {
new FilePart { ETag = "etag1", PartNumber = 1 },
new FilePart { ETag = "etag2", PartNumber = 2 }
};
Response<UploadDetails> upload = await client.Files.CompleteMultipartUpload(spaceId, uploadId, partsList);

Poll the upload status.

// Define a callback action to process the upload details
Action<UploadDetails> callback = (response) =>
{
Console.WriteLine($"Upload status: {response.Result.Status}");
};
try
{
// Call WaitForUpload with a specific timeout and interval
var timeout = TimeSpan.FromSeconds(300); // 5 minutes
var interval = TimeSpan.FromSeconds(10); // 10 seconds between checks
Console.WriteLine("Waiting for upload to complete...");
var upload = await client.Files.WaitForUpload(new Guid("<SPACE_ID>"), new Guid("<UPLOAD_ID>"), timeout, interval, callback);
// Process the final upload details
if (!upload.GetResponse().IsError)
{
Console.WriteLine($"Upload completed successfully: {upload.Data.Result.Message}");
}
else
{
Console.WriteLine("Upload completion check failed or timed out.");
}
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}

The optional urlDuration parameter can be used to specify the upload URL validity duration when polling. This ensures the URL remains valid throughout the polling period.

var urlDuration = TimeSpan.FromHours(2); // Custom URL duration
var timeout = TimeSpan.FromSeconds(300);
var interval = TimeSpan.FromSeconds(10);
var upload = await client.Files.WaitForUpload(
new Guid("<SPACE_ID>"),
new Guid("<UPLOAD_ID>"),
urlDuration,
timeout,
interval,
callback);

Poll the malware scan status of a file until it is completed.

// Define a callback action to process the malware scan status
Action<MalwareScanStatus?> callback = (status) =>
{
Console.WriteLine($"Malware scan status: {status}");
};
try
{
// Call PollForMalwareScanCompletion with a specific timeout and interval
var timeout = TimeSpan.FromSeconds(300); // 5 minutes
var interval = TimeSpan.FromSeconds(5); // 5 seconds between checks
Console.WriteLine("Polling for malware scan completion...");
await client.Files.PollForMalwareScanCompletion(new Guid("<SPACE_ID>"), new Guid("<FILE_ID>"), timeout, interval, callback);
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}

Update file by ID. Only the metadata, ACL settings and links can be updated.

Response<File> file = await client.Files.Update(spaceId, fileId, new FileUpdate()
{
Metadata = new Dictionary<string, object>
{
{ "key1", "value1" },
{ "key2", "value2" }
},
PermissionsLocal = new FileUpdatePermissionsLocal()
{
ReplaceAcl = new List<Acl>()
{
new Acl() { Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")), Role = AclRole.ContentContributor },
new Acl() { Actor = new AclUserIdentity(Guid.Parse("<USER_ID>")), Role = AclRole.ContentViewer }
}
},
Links = new Dictionary<string, SupportFileLink>()
{
{ "<KEY>", new SupportFileLink() { Id = new Guid("<SUPPORT_FILE_ID>") } }
}
});

The File Service supports file-level permissions with version restrictions using the new FileAcl property. This allows you to specify which file versions an actor can access.

Using the new FileAcl with version support:

Response<File> file = await client.Files.Update(spaceId, fileId, new FileUpdate()
{
PermissionsLocal = new FileUpdatePermissionsLocal()
{
ReplaceFileAcl = new List<FileAcl>()
{
new FileAcl()
{
Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")),
Role = AclRole.ContentViewer,
Versions = new List<string>() { "1", "2" }, // Access only to versions 1 and 2
AccessExpiresAt = DateTime.UtcNow.AddDays(30)
},
new FileAcl()
{
Actor = new AclCustomIdentity("anonymous"),
Role = AclRole.LimitedViewer,
AccessExpiresAt = DateTime.UtcNow.AddDays(7)
}
}
}
});

Using FileUpdateAcl for adding/removing permissions:

Response<File> file = await client.Files.Update(spaceId, fileId, new FileUpdate()
{
PermissionsLocal = new FileUpdatePermissionsLocal()
{
UpdateAcl = new FileUpdateAcl()
{
AddFileAcl = new List<FileAcl>()
{
new FileAcl()
{
Actor = new AclUserIdentity(Guid.Parse("<USER_ID>")),
Role = AclRole.ContentContributor,
Versions = new List<string>() { "1.1" }, // Access to only minor version
AccessExpiresAt = DateTime.UtcNow.AddDays(30)
}
},
Remove = new List<AclActor>()
{
new AclActor() { Actor = new AclCustomIdentity("old-user") }
}
}
}
});

Backward compatibility with deprecated Acl property:

Response<File> file = await client.Files.Update(spaceId, fileId, new FileUpdate()
{
PermissionsLocal = new FileUpdatePermissionsLocal()
{
ReplaceAcl = new List<Acl>()
{
new Acl() { Actor = new AclApplicationIdentity(Guid.Parse("<APPLICATION_ID>")), Role = AclRole.ContentContributor },
new Acl() { Actor = new AclUserIdentity(Guid.Parse("<USER_ID>")), Role = AclRole.ContentViewer }
}
}
});

The Versions property in FileAcl accepts version strings in the following formats:

  • Specific version: "1", "2.0", "1.5" - Access to a specific version
  • Major version wildcard: "1", "2" - Access to all minor versions of a major version
  • Multiple versions: ["1", "2", "3.2"] - Access to multiple specific versions

NOTE: The Versions property is only available with the new FileAcl property and is not supported by the deprecated Acl property.

You can also include headers in the request, such as If-Match for conditional updates:

var file = await client.Files.Update(spaceId, fileId, new FileUpdate()
{
Metadata = new Dictionary<string, object>()
{
{ "new", "value1" },
{ "newKey", "value2" }
},
}, new Dictionary<string, string>()
{
{ "<HEADER1>", "VALUE1" }
});

To update a file and get a minimal response, use the UpdateWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.UpdateWithMinimalResponse(spaceId, fileId, new FileUpdate()
{
Metadata = new Dictionary<string, object>
{
{ "key1", "value1" }
}
});

You can also include headers with the minimal response version:

Response<MinimalFile> file = await client.Files.UpdateWithMinimalResponse(spaceId, fileId, new FileUpdate()
{
Metadata = new Dictionary<string, object>
{
{ "key1", "value1" }
}
}, new Dictionary<string, string>()
{
{ "<HEADER1>", "<VALUE1>" }
});

Deletes the file. By default, it is a soft delete operation.

Delete for files that have support files is an asynchronous operation which returns the job ID.

Guid? jobId = await client.Files.Delete(spaceId, fileId);

The optional permanent parameter can be used to delete the file permanently.

Guid? jobId = await client.Files.Delete(spaceId, fileId, permanent: true);

You can also include headers in the request

Move a file to a new location within the same space. The file will be moved to the target location and the file identifier will remain the same.

The move operation is immediate and the response contains the updated parent ID.

Response<File> file = await client.Files.Move(spaceId, folderId, targetParentId);

To move a file and get a minimal response, use the MoveWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.MoveWithMinimalResponse(spaceId, folderId, targetParentId);

Rename a file within the same space. The file identifier will remain the same.

The rename operation is immediate and the response contains the updated file name.

Response<File> file = await client.Files.Rename(spaceId, fileId, "<NEW_FILE_NAME>");

To rename a file and get a minimal response, use the RenameWithMinimalResponse method.

You can also include headers in the request.

Response<File> file = await client.Files.Move(spaceId, fileId, targetParentId, new Dictionary<string, string>()
{
{ "<HEADER1>", "VALUE1" }
}, name: "NewFileName");

Copies a file from one folder to another within the given space. The copy operation is asynchronous and returns a job.

(Response<File> File, Guid? JobId) result = await client.Files.Copy(spaceId, fileId, targetParentId);

NOTE: The copy operation is not supported across different spaces and copies only the latest version.

The optional name parameter can be used to specify a new name for the copied folder. The optional includeSupportFiles parameter, if true, copies the support files along with the file and creates links between the copied file and the copied support files. The overwriteExisting query parameter, if specified and true, determines whether to overwrite an existing resource by creating a new version with the copied content.

(Response<File> File, Guid? JobId) result = await client.Files.Copy(spaceId, fileId, targetParentId, name: "<NEW_FILE_NAME>", includeSupportFiles: true, overwriteExisting: true);

To copy a file and get a minimal response, use the CopyWithMinimalResponse method.

(Response<MinimalFile> File, Guid? JobId) result = await client.Files.CopyWithMinimalResponse(spaceId, fileId, targetParentId);

Restore a file from the deleted state.

(Response<File> File, Guid? JobId) result = await client.Files.Restore(spaceId, fileId);

The optional name parameter can be used to specify a new name for the restored file and the targetParentId parameter can be used to restore the file to a new location. You can also include headers in the request.

(Response<File> File, Guid? JobId) result = await client.Files.Restore(spaceId, fileId, new Dictionary<string, string>()
{
{ "<HEADER1>", "VALUE1" }
}, name: "<NEW_FILE_NAME>", targetParentId: targetParentId);

To restore a file and get a minimal response, use the RestoreWithMinimalResponse method.

(Response<MinimalFile> File, Guid? JobId) result = await client.Files.RestoreWithMinimalResponse(spaceId, fileId);

List all files from inside an unpacked fileset. This method retrieves the manifest files contained within a fileset, allowing you to access individual files within an archive or container file.

var fileManifest = await client.Files.ListManifestFiles(spaceId, fileId);

The optional maxItems parameter can be used to limit the number of items returned in each page, the nextPageToken parameter can be used to get the next list of items, and the urlDuration parameter can be used to specify the URL validity duration.

var fileManifest = await client.Files.ListManifestFiles(spaceId, fileId, nextPageToken: "<NEXT_PAGE_TOKEN>", maxItems: 50, urlDuration: TimeSpan.FromHours(2));

Lock a file within a space. Locking a file will prevent other actors from creating a new version or deleting the file.

A locked file will be deleted in a recursive parent deletion. Support files cannot be locked.

Response<File> file = await client.Files.Lock(spaceId, fileId);

The optional reason parameter can be used to specify the reason for locking the file.

Response<File> file = await client.Files.Lock(spaceId, fileId, reason: "Reason for locking the file");

To lock a file and get a minimal response, use the LockWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.LockWithMinimalResponse(spaceId, fileId);

Unlock a file within a space. Unlocking a file will allow other actors to create a new version or delete the file.

The actor who locked the file or an actor with the ContentManager role attached to the file or parent resource is allowed to unlock the file.

Response<File> file = await client.Files.Unlock(spaceId, fileId);

To unlock a file and get a minimal response, use the UnlockWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.UnlockWithMinimalResponse(spaceId, fileId);

Get a specific version of a file by ID.

Response<File> file = await client.Files.GetVersion(spaceId, fileId, versionId: "2.0");

NOTE: To get the latest minor version of a major version series, the versionId should be provided as major_version.* which will return the details of the latest minor version of the major version.

For example: To get the latest minor version of the major version 2, the versionId should be provided as 2.*.

The optional status parameter can be used to filter the file versions based on the status, the urlDuration parameter can be used to specify the download URL validity duration and the responseContentType parameter can be used to specify the content type of the response. The default value for urlDuration is 1 hour.

Response<File> file = await client.Files.GetVersion(spaceId, fileId, versionId: "2.0", status: ResourceStatus.All, urlDuration: TimeSpan.FromMinutes(300), responseContentType: "application/json");

To get a file version with minimal response, use the GetVersionWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.GetVersionWithMinimalResponse(spaceId, fileId, versionId: "2.0");

Get a specific version of a file by path.

Response<File> file = await client.Files.GetVersion(spaceId, "<FILE_PATH>", versionId: "1.2");

NOTE: To get the latest minor version of a major version series, the versionId should be provided as major_version.* which will return the details of the latest minor version of the major version.

For example: To get the latest minor version of the major version 2, the versionId should be provided as 2.*.

The optional status parameter can be used to filter the file versions based on the status, the urlDuration parameter can be used to specify the download URL validity duration and the responseContentType parameter can be used to specify the content type of the response. The default value for urlDuration is 1 hour.

Response<File> file = await client.Files.GetVersion(spaceId, "<FILE_PATH>", versionId: "1.2", status: ResourceStatus.All, urlDuration: TimeSpan.FromMinutes(300), responseContentType: "application/json");

To get a file version with minimal response, use the GetVersionWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.GetVersionWithMinimalResponse(spaceId, "<FILE_PATH>", versionId: "1.2");

Get list of the file versions by ID.

do
{
var response = await client.Files.ListVersions(spaceId, fileId, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page and the listFilter parameter can be used to filter the list of versions.

do
{
var listFilterCriteria = new ListFilterCriteria { Status = ResourceStatus.All, UrlDuration = TimeSpan.FromMinutes(300) };
var response = await client.Files.ListVersions(spaceId, fileId, nextPageToken, maxItems: 10, listFilter: listFilterCriteria);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

To get the file versions with minimal response, use the ListVersionsWithMinimalResponse method.

do
{
var response = await client.Files.ListVersionsWithMinimalResponse(spaceId, fileId, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

Get list of the file versions by path.

do
{
var response = await client.Files.ListVersions(spaceId, path, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page and the listFilter parameter can be used to filter the list of versions.

do
{
var listFilterCriteria = new ListFilterCriteria { Status = ResourceStatus.All, UrlDuration = TimeSpan.FromMinutes(300) };
var response = await client.Files.ListVersions(spaceId, path, nextPageToken, maxItems: 20, listFilter: listFilterCriteria);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

To get the file versions with minimal response, use the ListVersionsWithMinimalResponse method.

do
{
var response = await client.Files.ListVersionsWithMinimalResponse(spaceId, path, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

Get list of the support files by file ID.

do
{
var response = await client.Files.ListSupportFiles(spaceId, fileId, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page and the listFilter parameter can be used to filter the list of support files.

do
{
var listFilterCriteria = new ListFilterCriteria { Status = ResourceStatus.All, UrlDuration = TimeSpan.FromMinutes(300) };
var response = await client.Files.ListSupportFiles(spaceId, fileId, nextPageToken, maxItems: 10, listFilter: listFilterCriteria);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

To get the support files with minimal response, use the ListSupportFilesWithMinimalResponse method.

do
{
var response = await client.Files.ListSupportFilesWithMinimalResponse(spaceId, fileId, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

Get list of the support files by file path.

do
{
var response = await client.Files.ListSupportFiles(spaceId, path, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

The optional maxItems parameter can be used to limit the number of items returned in each page and the listFilter parameter can be used to filter the list of support files.

do
{
var listFilterCriteria = new ListFilterCriteria { Status = ResourceStatus.All, UrlDuration = TimeSpan.FromMinutes(300) };
var response = await client.Files.ListSupportFiles(spaceId, path, nextPageToken, maxItems: 20, listFilter: listFilterCriteria);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

To get the support files with minimal response, use the ListSupportFilesWithMinimalResponse method.

do
{
var response = await client.Files.ListSupportFilesWithMinimalResponse(spaceId, path, nextPageToken);
foreach (var item in response)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
nextPageToken = response.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));

Check out a file within a space. Checking out a file will lock it and prevent other users from making changes while you are working on it.

Response<File> file = await client.Files.CheckOutFile(spaceId, fileId, "Reason for check out");

You can also include headers in the request

Response<File> file = await client.Files.CheckOutFile(spaceId, fileId, "Reason for check out", new Dictionary<string, string>()
{
{ "<HEADER1>", "VALUE1" }
});

To check out a file and get a minimal response, use the CheckOutFileWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.CheckOutFileWithMinimalResponse(spaceId, fileId, "Reason for check out");

Check in a file that was previously checked out. This will unlock the file and make it available for other users to modify.

Response<File> file = await client.Files.CheckInFile(spaceId, fileId);

To check in a file and get a minimal response, use the CheckInFileWithMinimalResponse method.

Response<MinimalFile> file = await client.Files.CheckInFileWithMinimalResponse(spaceId, fileId);
  • A job is a background process that is triggered by the user.
  • Async operations will return a job ID which can be used to track the status of the operation.

Get job by ID.

Response<Job> job = await client.Jobs.Get(new Guid("<JOB_ID>"));

The optional parameters can be added using GetJobQueryParams

### Wait for Job
Poll job status by ID.
```c#
// Define a callback action to process the job response
Action<Job> callback = (response) =>
{
Console.WriteLine($"Job status: {response.Status}");
};
try
{
// Call WaitForJob with a specific timeout and interval
var timeout = TimeSpan.FromSeconds(300); // 5 minutes
var interval = TimeSpan.FromSeconds(10); // 10 seconds between checks
Console.WriteLine("Waiting for job to complete...");
var job = await client.Jobs.WaitForJob(new Guid("<JOB_ID>"), timeout, interval, callback);
// Process the final job response
if (!job.GetResponse().IsError)
{
Console.WriteLine($"Job completed successfully: {job.Data.Message}");
}
else
{
Console.WriteLine("Job completion check failed or timed out.");
}
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}

Export is used to zip all children of a folder into a single file. Exports persist for 30 days and capture the state of the folder and its children at the time of creation, with no subsequent changes reflected. It is created in the same cloud provider as the space.

Create an export.

Guid exportId = await client.Exports.Create(spaceId, folderId);

Get an export by ID.

Response<Export> export = await client.Exports.Get(spaceId, exportId);

The optional urlDuration parameter can be used to specify the download URL validity duration. The default value for urlDuration is 1 hour.

Response<Export> export = await client.Exports.Get(spaceId, exportId, urlDuration: TimeSpan.FromMinutes(120));
  • Resources in File Service represent either files or folders.
  • This API provides methods to retrieve resources by ID, path, or in batches.

Get resource by ID.

Response<ResourceBase> resource = await client.Resources.Get(spaceId, resourceId);
if (resource.Data.Type.Equals(ResourceType.File))
{
if (resource.Data is MinimalFile minimalFile)
{
MinimalFile minimalFile = (MinimalFile)resource.Data;
}
else if (resource.Data is File)
{
File file = (File)resource.Data;
}
}

The optional status parameter can be used to filter the resources based on the status, the urlDuration parameter can be used to specify the download URL validity duration, and the responseContentType parameter can be used to specify the content type of the response. The default value for urlDuration is 1 hour.

Response<ResourceBase> resource = await client.Resources.Get(spaceId, resourceId, status: ResourceStatus.Active, urlDuration: TimeSpan.FromMinutes(300), responseContentType: "application/json");

To get a resource with minimal response, use the GetWithMinimalResponse method.

Response<ResourceBase> resource = await client.Resources.GetWithMinimalResponse(spaceId, resourceId, status: ResourceStatus.Active);

Get resource by path.

Response<ResourceBase> resource = await client.Resources.Get(spaceId, "<RESOURCE_PATH>");

The optional parameters work the same as for the Get by ID method.

Response<ResourceBase> resource = await client.Resources.Get(spaceId, "<RESOURCE_PATH>", status: ResourceStatus.Active, urlDuration: TimeSpan.FromMinutes(300), responseContentType: "application/json");

To get a resource with minimal response, use the GetWithMinimalResponse method.

Response<ResourceBase> resource = await client.Resources.GetWithMinimalResponse(spaceId, "<RESOURCE_PATH>", status: ResourceStatus.Active);

Get multiple resources by their IDs in a single request.

IList<Guid> resourceIds = new List<Guid> { resourceId1, resourceId2, resourceId3 };
Response<BatchResourceListResponse> resources = await client.Resources.BatchGet(spaceId, resourceIds);
IList<ResourceBase> list = resources.Data.Items;

The optional parameters can be used as with the individual resource retrieval methods.

Response<BatchResourceListResponse> resources = await client.Resources.BatchGet(spaceId, resourceIds, status: ResourceStatus.Active, urlDuration: TimeSpan.FromMinutes(300), responseContentType: "application/json");

To get batch resources with minimal response, use the BatchGetWithMinimalResponse method.

Response<BatchResourceListResponse> resources = await client.Resources.BatchGetWithMinimalResponse(spaceId, resourceIds, status: ResourceStatus.Active);

Get multiple resources by their paths in a single request.

IList<string> resourcePaths = new List<string> { "<RESOURCE_PATH_1>", "<RESOURCE_PATH_2>", "<RESOURCE_PATH_3>" };
Response<BatchResourceListResponse> resources = await client.Resources.BatchGet(spaceId, resourcePaths);

The optional parameters can be used as with the other methods.

Response<BatchResourceListResponse> resources = await client.Resources.BatchGet(spaceId, resourcePaths, status: ResourceStatus.Active, urlDuration: TimeSpan.FromMinutes(300), responseContentType: "application/json");

To get batch resources with minimal response, use the BatchGetWithMinimalResponse method.

Response<BatchResourceListResponse> resources = await client.Resources.BatchGetWithMinimalResponse(spaceId, resourcePaths, status: ResourceStatus.Active);
  • An object type defines the schema and actions for objects. It acts as a template that objects must conform to.

Create a new object type definition.

Response<ObjectType> objectType = await client.ObjectTypes.Create(new ObjectTypeCreate()
{
Name = "<OBJECT_TYPE_NAME>",
DisplayName = "<DISPLAY_NAME>",
Schema = "<JSON_SCHEMA_STRING>",
Actions = "<ACTIONS_JSON_STRING>"
});

Get an object type by ID.

Response<ObjectType> objectType = await client.ObjectTypes.Get(new Guid("<OBJECT_TYPE_ID>"));
  • Objects are containers for external resources made accessible through Connect.
  • Each object conforms to an object type schema.

Create a new object.

Response<ObjectEntity> obj = await client.Objects.Create(spaceId, new ObjectCreate()
{
ParentId = new Guid("<PARENT_FOLDER_ID>"),
Name = "<OBJECT_NAME>",
ObjectTypeId = new Guid("<OBJECT_TYPE_ID>"),
Content = new Dictionary<string, object>
{
{ "id", "<CONTENT_ID>" },
{ "detailsId", "<CONTENT_DETAILS_ID>" }
}
});

To create an object and get a minimal response, use the CreateWithMinimalResponse method.

Response<MinimalObjectEntity> obj = await client.Objects.CreateWithMinimalResponse(spaceId, new ObjectCreate()
{
ParentId = new Guid("<PARENT_FOLDER_ID>"),
Name = "<OBJECT_NAME>",
ObjectTypeId = new Guid("<OBJECT_TYPE_ID>"),
Content = new Dictionary<string, object>
{
{ "id", "<CONTENT_ID>" },
{ "detailsId", "<CONTENT_DETAILS_ID>" }
}
});

Get an object by ID.

Response<ObjectEntity> obj = await client.Objects.Get(spaceId, objectId);

Optional parameters can be passed using GetObjectParams:

Response<ObjectEntity> obj = await client.Objects.Get(spaceId, objectId, new GetObjectParams { Status = ResourceStatus.Active });

To get an object with minimal response, use the GetWithMinimalResponse method.

Response<MinimalObjectEntity> obj = await client.Objects.GetWithMinimalResponse(spaceId, objectId);

Get an object by path.

Response<ObjectEntity> obj = await client.Objects.Get(spaceId, "<OBJECT_PATH>");

To get an object with minimal response, use the GetWithMinimalResponse method.

Response<MinimalObjectEntity> obj = await client.Objects.GetWithMinimalResponse(spaceId, "<OBJECT_PATH>");

Update an object by ID. Only the content can be updated.

Response<ObjectEntity> obj = await client.Objects.Update(spaceId, objectId, new ObjectUpdate()
{
Content = new Dictionary<string, object>
{
{ "id", "<UPDATED_CONTENT_ID>" },
{ "detailsId", "<UPDATED_CONTENT_DETAILS_ID>" }
}
});

You can also include headers in the request for conditional updates:

Response<ObjectEntity> obj = await client.Objects.Update(spaceId, objectId, new ObjectUpdate()
{
Content = new Dictionary<string, object>
{
{ "id", "<UPDATED_CONTENT_ID>" },
{ "detailsId", "<UPDATED_CONTENT_DETAILS_ID>" }
}
}, new Dictionary<string, string>()
{
{ "If-Match", "2" }
});

To update an object and get a minimal response, use the UpdateWithMinimalResponse method.

Response<MinimalObjectEntity> obj = await client.Objects.UpdateWithMinimalResponse(spaceId, objectId, new ObjectUpdate()
{
Content = new Dictionary<string, object>
{
{ "id", "<UPDATED_CONTENT_ID>" }
}
});

Delete an object by ID. By default, it is a soft delete operation.

await client.Objects.Delete(spaceId, objectId);

The optional permanent parameter can be used to delete the object permanently.

await client.Objects.Delete(spaceId, objectId, permanent: true);

You can also include headers in the request.

await client.Objects.Delete(spaceId, objectId, permanent: false, new Dictionary<string, string>()
{
{ "If-Match", "2" }
});

Check out an object within a space. Checking out an object will lock it and prevent other users from making changes while you are working on it.

Response<ObjectEntity> obj = await client.Objects.Checkout(spaceId, objectId, reason: "<CHECKOUT_REASON>");

You can also include headers in the request.

Response<ObjectEntity> obj = await client.Objects.Checkout(spaceId, objectId, reason: "<CHECKOUT_REASON>", new Dictionary<string, string>()
{
{ "<HEADER>", "<VALUE>" }
});

To check out an object and get a minimal response, use the CheckoutWithMinimalResponse method.

Response<MinimalObjectEntity> obj = await client.Objects.CheckoutWithMinimalResponse(spaceId, objectId, reason: "<CHECKOUT_REASON>");

Check in an object that was previously checked out. This will unlock the object and make it available for other users to modify.

Response<ObjectEntity> obj = await client.Objects.Checkin(spaceId, objectId);

To check in an object and get a minimal response, use the CheckinWithMinimalResponse method.

Response<MinimalObjectEntity> obj = await client.Objects.CheckinWithMinimalResponse(spaceId, objectId);

Move an object to a new location within the same space.

Response<ObjectJobResponse> result = await client.Objects.Move(spaceId, objectId, targetParentId);

The optional name parameter can be used to specify a new name for the moved object. You can also include headers in the request.

Response<ObjectJobResponse> result = await client.Objects.Move(spaceId, objectId, targetParentId, "<NEW_OBJECT_NAME>", new Dictionary<string, string>()
{
{ "<HEADER>", "<VALUE>" }
});

To move an object and get a minimal response, use the MoveWithMinimalResponse method.

Response<MinimalObjectJobResponse> result = await client.Objects.MoveWithMinimalResponse(spaceId, objectId, targetParentId);

Rename an object with a new name. The object ID will remain the same.

Response<ObjectJobResponse> result = await client.Objects.Rename(spaceId, objectId, "<NEW_OBJECT_NAME>");

You can also include headers in the request.

Response<ObjectJobResponse> result = await client.Objects.Rename(spaceId, objectId, "<NEW_OBJECT_NAME>", new Dictionary<string, string>()
{
{ "<HEADER>", "<VALUE>" }
});

To rename an object and get a minimal response, use the RenameWithMinimalResponse method.

Response<MinimalObjectJobResponse> result = await client.Objects.RenameWithMinimalResponse(spaceId, objectId, "<NEW_OBJECT_NAME>");

Restore a deleted object. By default, the object will be restored to its original location.

Response<ObjectJobResponse> result = await client.Objects.Restore(spaceId, objectId);

The optional targetParentId parameter can be used to restore the object to a new location, and the name parameter can be used to specify a new name. You can also include headers in the request.

Response<ObjectJobResponse> result = await client.Objects.Restore(spaceId, objectId, targetParentId: targetParentId, name: "<NEW_OBJECT_NAME>", new Dictionary<string, string>()
{
{ "<HEADER>", "<VALUE>" }
});

To restore an object and get a minimal response, use the RestoreWithMinimalResponse method.

Response<MinimalObjectJobResponse> result = await client.Objects.RestoreWithMinimalResponse(spaceId, objectId);

Get list of the object versions by ID.

var versions = await client.Objects.ListVersions(spaceId, objectId);
foreach (var version in versions)
{
Console.WriteLine(version.Id);
}

Optional parameters can be passed using ListObjectVersionsParams:

var versions = await client.Objects.ListVersions(spaceId, objectId, new ListObjectVersionsParams { MaxItems = 10 });

To get object versions with minimal response, use the ListVersionsWithMinimalResponse method.

var versions = await client.Objects.ListVersionsWithMinimalResponse(spaceId, objectId);

Get list of the object versions by path.

var versions = await client.Objects.ListVersions(spaceId, "<OBJECT_PATH>");

To get object versions with minimal response, use the ListVersionsWithMinimalResponse method.

var versions = await client.Objects.ListVersionsWithMinimalResponse(spaceId, "<OBJECT_PATH>");

Get a specific version of an object by ID.

Response<ObjectEntity> version = await client.Objects.GetVersion(spaceId, objectId, versionId: 1);

Optional parameters can be passed using GetObjectVersionParams:

Response<ObjectEntity> version = await client.Objects.GetVersion(spaceId, objectId, versionId: 1, new GetObjectVersionParams { Status = ResourceStatus.Active });

Get a specific version of an object by path.

Response<ObjectEntity> version = await client.Objects.GetVersion(spaceId, "<OBJECT_PATH>", versionId: 1);

Link support files to a specific version of an object. The support files will be associated with the specified object version and the updated object entity is returned.

Response<ObjectEntity> obj = await client.Objects.LinkSupportFiles(spaceId, objectId, versionId: 1, new ObjectLink()
{
Links = new Dictionary<string, ObjectSupportFileDetails>
{
{
"<LINK_NAME>", new ObjectSupportFileDetails()
{
Id = new Guid("<SUPPORT_FILE_ID>")
}
}
}
});

The optional parentMajorVersion property on ObjectSupportFileDetails can be used to link the support file to a specific major version of the object.

Response<ObjectEntity> obj = await client.Objects.LinkSupportFiles(spaceId, objectId, versionId: 1, new ObjectLink()
{
Links = new Dictionary<string, ObjectSupportFileDetails>
{
{
"<LINK_NAME>", new ObjectSupportFileDetails()
{
Id = new Guid("<SUPPORT_FILE_ID>"),
ParentMajorVersion = 1
}
}
}
});

To link support files and get a minimal response, use the LinkSupportFilesWithMinimalResponse method.

Response<MinimalObjectEntity> obj = await client.Objects.LinkSupportFilesWithMinimalResponse(spaceId, objectId, versionId: 1, new ObjectLink()
{
Links = new Dictionary<string, ObjectSupportFileDetails>
{
{
"<LINK_NAME>", new ObjectSupportFileDetails()
{
Id = new Guid("<SUPPORT_FILE_ID>")
}
}
}
});

Get list of the support files (resources) associated with an object by ID.

var resources = await client.Objects.ListResources(spaceId, objectId);
foreach (var resource in resources)
{
Console.WriteLine(resource.Id);
}

Optional parameters can be passed using ListObjectResourcesParams:

var resources = await client.Objects.ListResources(spaceId, objectId, new ListObjectResourcesParams { MaxItems = 20 });

Get list of the support files (resources) associated with an object by path.

var resources = await client.Objects.ListResources(spaceId, "<OBJECT_PATH>");