# Upgrade to API Version 28

> How to upgrade your Kiteworks API integration to v28: add the version header, handle version errors, replace removed endpoints, and update removed request parameters.

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](upgrade-check-version.html).

## Step 1 — Add the Version Header

Every API request must include this header:

http Copy

```plaintext
X-Accellion-Version: 28
```

cURL Python

add-version-header.sh Copy

```bash
curl -s \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "X-Accellion-Version: 28" \
  "https://your-instance.kiteworks.com/rest/folders/top"
```

add_version_header.py Copy

```python
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 Copy

```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 Copy

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

### Very old version specified (v1–v4)

json Copy

```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 Copy

```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 Copy

```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 Copy

```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 Copy

```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](#lock-unlock-migration) and [mark-as-read and mark-as-unread](#mail-read-migration) 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 `wipeDevices` → `remoteWipe` and `withdrawSendFiles` → `withdrawFileLinks` 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).** Follow the [Files & Folders UUID update guide](upgrade-uuid-files-folders.html).
- **Update Mail & Email to UUID (if on v20 or earlier).** Follow the [Mail & Email UUID update guide](upgrade-uuid-mail.html).
- **Update Users to UUID (if on v21 or earlier).** Follow the [Users UUID update guide](upgrade-uuid-users.html).

## 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:

- [Check Your API Version →](upgrade-check-version.html) Verify your integration is sending `X-Accellion-Version: 28`.
- [Update Files & Folders to UUID (v18 to v19+) →](upgrade-uuid-files-folders.html) Migrate file and folder IDs if you haven't applied this change yet.
- [Update Mail & Email to UUID (v20 to v21+) →](upgrade-uuid-mail.html) Migrate mail and email IDs if you haven't applied this change yet.
- [Update Users to UUID (v21 to v22+) →](upgrade-uuid-users.html) Migrate user IDs if you haven't applied this change yet.
- [API Reference →](api-reference.html) Explore the full v28 spec.
