Sharing beta endpoints: paging and consolidated metadata

The beta sharing endpoints are being updated with paging support and a new dedicated membership endpoint. The changes also tighten up error reporting and consolidate metadata structures. None of these updates are backwards compatible, but they lay the groundwork for better scalability and simpler client logic. The revised API is available in the HTTP API and in the Swift, Python, .NET, and Java SDKs.

Paging for shared folder listing

Large sets of shared folders and their members will no longer produce slow, heavyweight responses. The sharing/list_folders and sharing/list_folder_members endpoints now return paginated results with an optional cursor field. When that field is present, more results are available, and callers must fetch them using the corresponding /continue endpoints, which accept the cursor:

  • sharing/list_folders/continue
  • sharing/list_folder_members/continue

Existing callers of sharing/list_folders need to update their logic to handle the optional cursor, otherwise they may end up processing only partial results.

struct ListFoldersResult
    entries List(SharedFolderMetadata)
    cursor String?

Dedicated membership endpoint

To properly support paging across shared folder members, membership is now available through two new endpoints:

  • sharing/list_folder_members
  • sharing/list_folder_members/continue

For consistency with other field names in the API, the members field in membership responses is now renamed to users:

{
    "users": [
        {
            "access_type": {
                ".tag": "owner"
            }, 
            "user": {
                "account_id": "dbid:AAH4f99T0taONIb-OurWxbNQ6ywGRopQngc", 
                "same_team": false
            }
        }
    ],
    "groups": [],
    "invitees": [],
    "cursor": "ZtkX9_EHj3x7PMkVuFIhwKYXEpwpLwyxp9vMKomUhllil9q7eWiAu"
}

Metadata consolidation in get_folder_metadata

With the membership endpoint in place, sharing/get_folder_metadata is being simplified. The following breaking changes apply:

  • Membership is no longer part of the response; use the new endpoint to list folder members.
  • The include_membership request parameter is no longer accepted.
  • The BasicSharedFolderMetadata and FullSharedFolderMetadata structures are combined into a single SharedFolderMetadata response type.
  • The id response field is renamed to shared_folder_id.

The revised response structure:

{
    "access_type": {
        ".tag": "owner"
    }, 
    "shared_folder_id": "dbsfid:BCcDKIi3BO5uA9Kzv1v7I9MBJiqoXZXx7Fo", 
    "is_team_folder": false, 
    "name": "example", 
    "path_lower": "/example", 
    "policy": {
        "acl_update_policy": {
            ".tag": "editors"
        }, 
        "member_policy": {
            ".tag": "anyone"
        }, 
        "shared_link_policy": {
            ".tag": "anyone"
        }
    }
}

Unified member error handling

Error tags and structures have been cleaned up across the sharing endpoints. All not_member errors are renamed to not_a_member for consistency. Additionally, SharedFolderMemberError is now the common error type for member-selector errors in two routes: sharing/update_folder_member and sharing/remove_folder_member.

The rename from not_member to not_a_member:

Old

SharedFolderAccessError.not_member
TransferFolderError.new_owner_not_member

New

SharedFolderAccessError.not_a_member
TransferFolderError.new_owner_not_a_member

Routes that allow operating on a target member via a member selector now use a shared SharedFolderMemberError type for bad selectors:

union SharedFolderMemberError
    invalid_dropbox_id
    not_a_member

The asynchronous sharing/remove_folder_member route loses two error tags that are redundant with the JobError tags already defined for asynchronous job failures. The sharing/update_folder_member route similarly replaces two of its error tags with the common SharedFolderMemberError type:

{
    "error_summary": "member_error/not_a_member/...",
    "error": {
        ".tag": "member_error",
        "member_error": {
            ".tag": "not_a_member"
        }
    }
}