Upgrade Guides

Upgrade to API Version 28

Kiteworks API v28 is the current and final supported version. All API requests must include the X-Accellion-Version: 28 header. This guide covers the required code changes: adding the version header, replacing 8 removed endpoints, and updating calls that used removed request parameters.

Who Is Affected

If your integration does not yet send X-Accellion-Version: 28 on every request, update it now. To confirm what version you currently send, see Check Your API Version.

Step 1 — Add the Version Header

Every API request must include this header:

http
X-Accellion-Version: 28
add-version-header.sh
curl -s \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "X-Accellion-Version: 28" \
  "https://your-instance.kiteworks.com/rest/folders/top"
add_version_header.py
import requests

session = requests.Session()
session.headers.update({
    "Authorization":       f"Bearer {access_token}",
    "X-Accellion-Version": "28",
})

folders = session.get(f"{base_url}/rest/folders/top").json()
The apiVersion query parameter (e.g. ?apiVersion=28) is supported on some endpoints as an alternative, but the header is preferred and works universally.

Step 2 — Update Your Error Handling for Version Errors

If your code still sends an old or missing version header, the API returns an error. The exact error format depends on the version requested and the endpoint.

No version header

json
// Most Flask-based endpoints
{
  "errors": [{ "code": "ERR_REQUEST_API_VERSION_MISSING", "message": "API version is not specified in the request." }]
}

Some older endpoints may silently treat the request as v1, returning unexpected results including ERR_REQUEST_NOT_FOUND. Always include X-Accellion-Version: 28.

Old version specified (v5–v27)

json
{
  "errors": [{ "code": "ERR_REQUEST_VERSION_NOT_SUPPORTED", "message": "Specified API version is not supported by server" }]
}

Very old version specified (v1–v4)

json
{
  "message": "Specified API version is not supported by server"
}
v1–v4 responses use a plain message field (no errors array) — a legacy error format. Update error-handling code to handle both formats.

Summary of version error behavior:

Scenario Error Code Format
No version header (most endpoints) ERR_REQUEST_API_VERSION_MISSING errors array
Version v5–v27 specified ERR_REQUEST_VERSION_NOT_SUPPORTED errors array
Version v1–v4 specified ERR_REQUEST_VERSION_NOT_SUPPORTED Plain message field
Version v28 No error

Step 3 — Replace Removed Endpoints

The following 8 endpoints no longer exist in v28. Find every call to the 8 endpoints below and replace them with their v28 replacement before you upgrade. The table below lists the old endpoint, when it was removed, and its v28 replacement.

Removed Endpoint Last Present In v28 Replacement Notes
GET /rest/folders/{id}/path v4.1 GET /rest/folders/{id} path field now included directly in the Folder response
GET /rest/admin/profiles/{id}/users/{user_id} v4.1 GET /rest/admin/profiles/{id}/users No single-user sub-resource in v28; filter client-side by user_id
POST /rest/sources/{parent_id}/actions/fileFromTemplate v5.1 POST /rest/folders/{parent_id}/actions/fileFromTemplate Namespace moved from /sources/ to /folders/
GET /rest/folders/members v6 GET /rest/folders/{id}/members Must scope query to a specific folder {id}
POST /rest/sources/{id}/actions/lock v7 PATCH /rest/sources/actions/lock Method: POST→PATCH; {id} path param → id:in query param (supports bulk)
POST /rest/sources/{id}/actions/unlock v7 PATCH /rest/sources/actions/unlock Method: POST→PATCH; {id} path param → id:in query param (supports bulk)
DELETE /rest/mail/{emailId}/actions/read v9 PATCH /rest/mail/actions/read Method: DELETE→PATCH; {emailId} path param → emailId:in query param (supports bulk)
DELETE /rest/mail/{emailId}/actions/unread v9 PATCH /rest/mail/actions/unread Method: DELETE→PATCH; {emailId} path param → emailId:in query param (supports bulk)

Update lock and unlock calls to use PATCH with a query parameter

The lock and unlock endpoints changed from POST with an {id} path parameter to PATCH with an id:in query parameter. The query parameter accepts a comma-separated list of Universally Unique Identifier (UUID) strings, so a single call can act on multiple items.

bash
# Old — lock one source item
curl -s -X POST "https://your-instance.kiteworks.com/rest/sources/12345/actions/lock" \
  -H "Authorization: Bearer $TOKEN"

# New v28 — lock one or more items (id:in is comma-separated)
curl -s -X PATCH "https://your-instance.kiteworks.com/rest/sources/actions/lock?id:in=550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Accellion-Version: 28"

Update mark-as-read and mark-as-unread calls to use PATCH

Both endpoints changed from DELETE with an {emailId} path parameter to PATCH with an emailId:in query parameter that accepts a comma-separated list of email UUIDs.

bash
# Old — mark one email as read
curl -s -X DELETE "https://your-instance.kiteworks.com/rest/mail/12345/actions/read" \
  -H "Authorization: Bearer $TOKEN"

# New v28 — mark one or more emails as read
curl -s -X PATCH "https://your-instance.kiteworks.com/rest/mail/actions/read?emailId:in=550e8400-e29b-41d4-a716-446655440001" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Accellion-Version: 28"

Step 4 — Replace Removed Request Parameters

Remove the user_ids parameter from GET /rest/files/{id}/members

Kiteworks removed the user_ids query parameter in v22. Remove it from all calls and filter members client-side if needed.

bash
# Old — filter by user IDs server-side (no longer works in v28)
GET /rest/files/{id}/members?user_ids=123,456

# New v28 — retrieve all members, filter client-side
GET /rest/files/{id}/members

Move user-delete options from query parameters to the request body

DELETE /rest/admin/users/{id} and DELETE /rest/users no longer accept delete options as query parameters. Three query parameters were removed and replaced by request body fields:

Removed Query Parameter Last Present In v28 Request Body Field Notes
userId v7.1 Use {id} path param (single) Path param replaced query param
wipeDevices v11 remoteWipe (boolean) Renamed in request body
withdrawSendFiles v11 withdrawFileLinks (boolean) Renamed in request body

The full v28 UserDeleteOptions request body:

Field Type Description
remoteWipe boolean Remotely wipe data from desktop and mobile devices
deleteUnsharedData boolean Delete data owned by the user
retainData boolean Retain and transfer data to another user
retainToUser string (UUID) ID of the new owner for transferred data
retainToAdvancedFormUser string (UUID) ID of user to receive advanced form data
retainPermissionToSharedData boolean Retain permissions to shared folders
withdrawRequestFiles boolean Withdraw all request files on deletion
withdrawFileLinks boolean Withdraw all sent file links on deletion
bash
# Old — options as query params
curl -s -X DELETE "https://your-instance.kiteworks.com/rest/admin/users/123?wipeDevices=true&withdrawSendFiles=true" \
  -H "Authorization: Bearer $TOKEN"

# New v28 — options in JSON request body; {id} is a UUID
curl -s -X DELETE "https://your-instance.kiteworks.com/rest/admin/users/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Accellion-Version: 28" \
  -H "Content-Type: application/json" \
  -d '{"remoteWipe": true, "withdrawFileLinks": true}'

Remove all 8 query parameters from PUT /rest/profiles/{id}

Kiteworks removed these 8 query parameters entirely in v8:

userId, wipeDevices, deleteUnsharedData, retainData, retainPermissionToSharedData, withdrawSendFiles, withdrawRequestFiles, mode

Remove all 8 from calls to PUT /rest/profiles/{id}. If your application triggers demote/delete operations during profile changes, use the UserDemoteOptions request body on the appropriate demote endpoints: PUT /rest/admin/profiles/{id}/users or DELETE /rest/profiles/{id}/replace/{new_profile}.

Update Checklist

  • Add the version header
    Add X-Accellion-Version: 28 to all API request headers.
  • Apply it globally
    Set it on a shared HTTP session or client so it applies to every call automatically.
  • Audit existing version values
    Search for X-Accellion-Version and apiVersion in your code to find any remaining old version values and update them.
  • Replace removed endpoints
    Search for each of the 8 removed endpoint paths and replace with their v28 equivalents (see Step 3 table).
  • Replace all 4 changed-method endpoints
    Update lock and unlock and mark-as-read and mark-as-unread calls — change the HTTP method and move the ID from the path to the query parameter (see Step 3 table for exact before/after).
  • Remove the user_ids parameter
    Remove user_ids query parameter from all GET /rest/files/{id}/members calls.
  • Update user delete parameters
    Move wipeDevicesremoteWipe and withdrawSendFileswithdrawFileLinks into the request body for user delete calls.
  • Remove deprecated profile parameters
    Remove all 8 query parameters from PUT /rest/profiles/{id} calls (see Step 4 table).
  • Update error handling
    Recognize both ERR_REQUEST_VERSION_NOT_SUPPORTED (errors array) and legacy plain message format.
  • Update Files & Folders to UUID (if on v18 or earlier)
  • Update Mail & Email to UUID (if on v20 or earlier)
  • Update Users to UUID (if on v21 or earlier)

Frequently Asked Questions

What happens if I omit the API version header?

Most Flask-based endpoints return ERR_REQUEST_API_VERSION_MISSING. Some older endpoints may silently treat the request as v1, producing unexpected results. Always include X-Accellion-Version: 28.

What happens if I specify an older API version such as v27?

The API returns ERR_REQUEST_VERSION_NOT_SUPPORTED (HTTP 400) with a structured errors array. All new clients must use v28.

Can I use the apiVersion query parameter instead of the header?

Yes, ?apiVersion=28 is supported on some endpoints as an alternative. However, the X-Accellion-Version header is preferred because it works universally across all endpoints.

Next Steps

You've applied all v28 API changes. Here's what to do next: