diff --git a/.codegen.json b/.codegen.json
index b69ae24ff..65cab0252 100644
--- a/.codegen.json
+++ b/.codegen.json
@@ -1 +1 @@
-{ "engineHash": "48e5311", "specHash": "fa34496", "version": "0.1.0" }
+{ "engineHash": "fa0419f", "specHash": "fa34496", "version": "0.1.0" }
diff --git a/migration-guides/3.x.x to 4.x.x.md b/migration-guides/3.x.x to 4.x.x.md
deleted file mode 100644
index 692d1167d..000000000
--- a/migration-guides/3.x.x to 4.x.x.md
+++ /dev/null
@@ -1,202 +0,0 @@
-# Migration guide for versions 3.x.x -> 4.x.x
-
-
-
-
-- [Configuration changes](#configuration-changes)
- - [BoxDeveloperEditionAPIConnection](#boxdevelopereditionapiconnection)
- - [MaxRequestAttempts](#maxrequestattempts)
-- [Removed deprecated methods and classes](#removed-deprecated-methods-and-classes)
-- [Replaced methods and classes](#replaced-methods-and-classes)
- - [Shared links](#shared-links)
- - [Retention Policies](#retention-policies)
- - [Enterprise Events](#enterprise-events)
- - [Search](#search)
- - [BoxGroup](#boxgroup)
- - [MetadataTemplate](#metadatatemplate)
- - [Others](#others)
-
-
-
-The most important change this release includes is the replacement of the HTTP library from a native one to
-OkHttp which allows SDK to:
-
- - Support the HTTP2 version of the HTTP protocol.
- - Support proxies that do not use only basic authentication method. For details on creating custom proxy authenticators and an example of
-NTLM proxy authentication, see [here](https://github.com/box/box-java-sdk/blob/kb/ok-http/doc/configuration.md#custom-proxy-authenticator).
-
-# Configuration changes
-
-## BoxDeveloperEditionAPIConnection
-Replaced `com.box.sdk.BoxDeveloperEditionAPIConnection#getAppUserConnection`with `com.box.sdk.BoxDeveloperEditionAPIConnection#getUserConnection`.
-
-### Example
-To create `com.box.sdk.BoxDeveloperEditionAPIConnection` configured for user access:
-```java
-Reader reader = new FileReader("some-config.json");
-BoxConfig boxConfig = BoxConfig.readFrom(reader);
-
-BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getUserConnection(boxConfig);
-```
-
-### Documentation
-You can read more on BoxDeveloperEditionAPIConnection [here](../../README.md#boxdevelopereditionapiconnectionasenterpriseuser).
-
-
-## MaxRequestAttempts
-The `MaxRequestAttempts` are removed from `com.box.sdk.BoxGlobalSettings` and replaced with `MaxRetryAttempts`.
-However, if you have API connection stored with the deprecated `MaxRequestAttempts` value it will be restored into `MaxRetryAttempts`.
-
-# Removed deprecated methods and classes
-1. `com.box.sdk.BoxAPIRequest.BoxAPIRequest(java.net.URL, java.lang.String)` - use constuctor that accepts `com.box.sdk.BoxAPIConnection`.
-2. `com.box.sdk.BoxUser.moveFolderToUser` - this method is removed as this operation is not allowed by API. You can only transfer root folder to another user using `com.box.sdk.BoxUser.transferContent`.
-
-# Replaced methods and classes
-
-## Getting thumbnail
-Method `com.box.sdk.BoxFile.getThumbnail` was removed. To get any file representation use `com.box.sdk.BoxFile.getRepresentationContent(java.lang.String, java.io.OutputStream)`
-or `com.box.sdk.BoxFile.getRepresentationContent(java.lang.String, java.lang.String, java.io.OutputStream)`.
-
-### Example
-To read the PDF representation of file with id `12345`:
-
-```java
-ByteArrayOutputStream output = new ByteArrayOutputStream();
-
-BoxFile file = new BoxFile(api, "12345");
-file.getRepresentationContent("[pdf]", output);
-```
-### Documentation
-
-For more details on getting representation content go [here](../files.md#get-representation-content).
-
-## Shared links
-Removed variant of methods that do not use `com.box.sdk.sharedlink.BoxSharedLinkRequest`:
-1. `com.box.sdk.BoxItem.createSharedLink`
-2. `com.box.sdk.BoxFile.createSharedLink`
-3. `com.box.sdk.BoxFolder.createSharedLink`
-4. `com.box.sdk.BoxWebLink.createSharedLink`
-
-### Example
-
-If you want to create a shared link, first create `com.box.sdk.sharedlink.BoxSharedLinkRequest`:
-```java
-Date unsharedDate = ...
-BoxFile file = new BoxFile(api, "id");
-BoxSharedLinkRequest sharedLinkRequest = new BoxSharedLinkRequest()
- .access(OPEN)
- .permissions(true, true)
- .unsharedDate(unsharedDate);
-
-BoxSharedLink sharedLink = file.createSharedLink(sharedLinkRequest);
-```
-
-### Documentation
-For details on shared links, see:
-1. [Create shared link for file](../files.md#create-a-shared-link)
-2. [Create shared link for folder](../folders.md#create-a-shared-link)
-3. [Create shared link for web link](../weblinks.md#create-shared-link)
-
-## Retention Policies
-Removed variant of methods that were not using `com.box.sdk.BoxRetentionPolicy.BoxRetentionPolicyAction`:
-1. `com.box.sdk.BoxRetentionPolicy.createFinitePolicy`
-
-### Example
-If you want to create a finite retention policy:
-```java
-BoxRetentionPolicy.createFinitePolicy(api, "My 30 days retention policy", 30, BoxRetentionPolicyAction.PermanentlyDelete);
-```
-
-### Documentation
-You can read more on creating retention policies [here](../retention_policies.md#create-retention-policy).
-
-## Enterprise Events
-Removed variant of methods that were not using `com.box.sdk.EnterpriseEventsRequest`:
-1. `com.box.sdk.EventLog.getEnterpriseEvents`
-### Example
-If you want to get historical enterprise events, first create `com.box.sdk.EnterpriseEventsRequest`:
-```java
-EnterpriseEventsRequest request = new EnterpriseEventsRequest().limit(20);
-EventLog.getEnterpriseEvents(api, request1);
-// process recieved events
-```
-### Documentation
-You can read more on getting enterprise events [here](../events.md#enterprise--admin--events).
-
-## Search
-Method `com.box.sdk.BoxFolder.search` is replaced with class `com.box.sdk.BoxSearch`.
-
-### Example
-If you would like to find the first 10 files matching "taxes":
-```java
-long offsetValue = 0;
-long limitValue = 10;
-BoxSearchParameters searchParams = new BoxSearchParameters();
-searchParams.setQuery("taxes");
-searchParams.setType("file");
-
-BoxSearch boxSearch = new BoxSearch(api);
-boxSearch.searchRange(offsetValue, limitValue, searchParams);
-```
-
-### Documentation
-You can read more on search [here](../search.md).
-
-## BoxGroup
-All methods that use `com.box.sdk.BoxGroupMembership.Role` were removed. Use ones that use `com.box.sdk.BoxGroupMembership.GroupRole`.
-Also `com.box.sdk.BoxGroupMembership.Role` was replaced with `com.box.sdk.BoxGroupMembership.GroupRole`.
-
-### Example
-To add a new member to a group with specific role:
-```java
-BoxUser user = ...
-BoxGroup boxGroup = new BoxGroup(api, "group_id");
-boxGroup.addMembership(user, BoxGroupMembership.GroupRole.ADMIN);
-```
-To get membership role use `com.box.sdk.BoxGroupMembership.Info.getGroupRole`:
-```java
-BoxGroupMembership membership = new BoxGroupMembership(api, "membership_id");
-membership.getInfo().getGroupRole();
-```
-
-To change membership role use `com.box.sdk.BoxGroupMembership.Info.setGroupRole`:
-```java
-BoxGroupMembership membership = new BoxGroupMembership(api, "membership_id");
-BoxGroupMembership.Info membershipInfo = membership.getInfo();
-membershipInfo.setGroupRole(BoxGroupMembership.GroupRole.MEMBER);
-membership.updateInfo(membershipInfo);
-```
-
-### Documentation
-You can read more on groups [here](../groups.md).
-
-## MetadataTemplate
-In `com.box.sdk.MetadataTemplate` methods that do not use `com.box.sdk.MetadataQuery` were removed.
-
-### Example
-To execute a metadata query first create `com.box.sdk.MetadataQuery` instance.
-```java
-MetadataQuery mQuery = new MetadataQuery("enterprise_341532.test");
-mQuery.setQuery("testfield = :arg");
-mQuery.setAncestorFolderId("0");
-mQuery.setOrderBy(
- MetadataQuery.OrderBy.ascending("primarySortKey"),
- MetadataQuery.OrderBy.ascending("secondarySortKey")
-);
-mQuery.addParameter("arg", "test");
-mQuery.setFields("metadata.enterprise_341532.test.customField");
-MetadataTemplate.executeMetadataQuery(api, mQuery);
-```
-
-### Documentation
-You can read more on how to execute metadata query [here](../metadata_template.md#execute-metadata-query).
-
-## Others
-| Old | New |
-|:-------------------------------------------------------|:--- |
- | `com.box.sdk.BoxEvent.getType` |`com.box.sdk.BoxEvent.getEventType` |
- | `com.box.sdk.BoxEvent.Type` | `com.box.sdk.BoxEvent.EventType` |
- | `com.box.sdk.BoxFile.uploadVersion` | `com.box.sdk.BoxFile.uploadNewVersion` |
- | `com.box.sdk.BoxGlobalSettings.getMaxRequestAttempts` | `com.box.sdk.BoxGlobalSettings.getMaxRetryAttempts` |
- | `com.box.sdk.BoxGlobalSettings.setMaxRequestAttempts` | `com.box.sdk.BoxGlobalSettings.setMaxRetryAttempts` |
- | `com.box.sdk.BoxTask.Info.getAction` | `com.box.sdk.BoxTask.Info.getTaskType` |
diff --git a/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md b/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md
new file mode 100644
index 000000000..be55c1b75
--- /dev/null
+++ b/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md
@@ -0,0 +1,149 @@
+# Migration guide from beta release (v0.X.Y) of the `box-java-sdk-gen` to the v10 version of the `box-java-sdk`
+
+
+
+
+- [Installation](#installation)
+ - [How to migrate](#how-to-migrate)
+ - [Maven](#maven)
+ - [Gradle](#gradle)
+- [Union classes name changes](#union-classes-name-changes)
+ - [How to migrate](#how-to-migrate-1)
+- [Removed unused models from schemas namespace](#removed-unused-models-from-schemas-namespace)
+ - [How to migrate](#how-to-migrate-2)
+
+
+
+## Installation
+
+In order to start using v10 version of the Box Java SDK, you need to change the dependency in your project.
+The artifact name has changed from `com.box:box-java-sdk-gen` to `com.box:box-java-sdk`.
+You also need to set the version to `10.0.0` or higher. You can find the latest version on [Maven Central](https://search.maven.org/artifact/com.box/box-java-sdk).
+
+### How to migrate
+
+#### Maven
+
+To start using v10 version of Box Java SDK in your Maven project replace the dependency in your `pom.xml` file.
+
+**Old (`box-java-sdk-gen-v0`)**
+
+```xml
+
+ com.box
+ box-java-sdk-gen
+ 0.8.0
+
+```
+
+**New (`box-java-sdk-v10`)**
+
+```xml
+
+ com.box
+ box-java-sdk
+ 10.0.0
+
+```
+
+#### Gradle
+
+To start using v10 version of Box Java SDK in your Gradle project replace the dependency in your `build.gradle` file.
+
+**Old (`box-java-sdk-gen-v0`)**
+
+```groovy
+implementation 'com.box:box-java-sdk-gen:0.8.0'
+```
+
+**New (`box-java-sdk-v10`)**
+
+```groovy
+implementation 'com.box:box-java-sdk:10.0.0'
+```
+
+## Union classes name changes
+
+In the beta version of the `box-java-sdk-gen` our `OneOf` class names (representing unions from the OpenAPI specification)
+were fully auto-generated based on the included variants. This often resulted in overly long names that were difficult
+to work with in tools like Git. For example: `MetadataFieldFilterDateRangeOrMetadataFieldFilterFloatRangeOrArrayOfStringOrNumberOrString`.
+Additionally, every time the new variant was added to the `OneOf`, the class name itself changed.
+Starting in v10, the names of `OneOf` classes are defined directly in the specification. This ensures that they are meaningful, short, and stable over time.
+
+### How to migrate
+
+If your code references any of the renamed classes, replace the old name with the new one.
+If you were not explicitly using the type names, no changes are needed, since only the class names changed and their behavior remains the same.
+
+List of changed `OneOf` classes and types associated with them:
+
+| Old name | New name |
+| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------ |
+| AiAgentAskOrAiAgentExtractOrAiAgentExtractStructuredOrAiAgentTextGen | AiAgent |
+| AiAgentAskOrAiAgentReference | AiAskAgent |
+| AiAgentExtractOrAiAgentReference | AiExtractAgent |
+| AiAgentExtractStructuredOrAiAgentReference | AiExtractStructuredAgent |
+| AiAgentReferenceOrAiAgentTextGen | AiTextGenAgent |
+| AppItemEventSourceOrEventSourceOrFileOrFolderOrGenericSourceOrUser | EventSourceResource |
+| FileBaseOrFolderBaseOrWebLinkBase | AppItemAssociatedItem |
+| FileFullOrFolderFull | MetadataQueryResultItem |
+| FileFullOrFolderFullOrWebLink | SearchResultWithSharedLinkItem/RecentItemResource/SearchResultItem |
+| FileFullOrFolderMiniOrWebLink | Item |
+| FileMiniOrFolderMini | Resource |
+| FileOrFolderOrWebLink | LegalHoldPolicyAssignedItem/CollaborationItem |
+| FileOrFolderScope | ResourceScope |
+| FileOrFolderScopeScopeField | ResourceScopeScopeField |
+| FileReferenceOrFolderReferenceOrWeblinkReferenceV2025R0 | HubItemReferenceV2025R0 |
+| GroupMiniOrUserCollaborations | CollaborationAccessGrantee |
+| IntegrationMappingPartnerItemSlackUnion | IntegrationMappingPartnerItemSlack |
+| IntegrationMappingPartnerItemTeamsUnion | IntegrationMappingPartnerItemTeams |
+| KeywordSkillCardOrStatusSkillCardOrTimelineSkillCardOrTranscriptSkillCard | SkillCard |
+| MetadataFieldFilterDateRangeOrMetadataFieldFilterFloatRangeOrArrayOfStringOrNumberOrString | MetadataFilterValue |
+| SearchResultsOrSearchResultsWithSharedLinks | SearchResultsResponse |
+
+Some classes were split into multiple ones depending on context.
+
+Manager functions affected by these changes:
+
+| Function | Old return type | New return type |
+| -------------------------------------- | -------------------------------------------------------------------- | --------------------- |
+| AiManager.getAiAgentDefaultConfig(...) | AiAgentAskOrAiAgentExtractOrAiAgentExtractStructuredOrAiAgentTextGen | AiAgent |
+| SearchManager.searchForContent(...) | SearchResultsOrSearchResultsWithSharedLinks | SearchResultsResponse |
+
+## Removed unused models from schemas namespace
+
+Several unused types (classes and enums) have been removed from the schemas because they were not used by any SDK functions or by the Box API.
+
+### How to migrate
+
+Here is the full list of removed types:
+
+| Removed classes/enums |
+| ------------------------------------------ |
+| FileOrFolder |
+| HubActionV2025R0 |
+| MetadataQueryIndex |
+| MetadataQueryIndexFieldsField |
+| MetadataQueryIndexFieldsSortDirectionField |
+| MetadataQueryIndexStatusField |
+| RetentionPolicyAssignmentBase |
+| RetentionPolicyAssignmentBaseTypeField |
+| SkillInvocation |
+| SkillInvocationEnterpriseField |
+| SkillInvocationEnterpriseTypeField |
+| SkillInvocationSkillField |
+| SkillInvocationSkillTypeField |
+| SkillInvocationStatusField |
+| SkillInvocationStatusStateField |
+| SkillInvocationTokenField |
+| SkillInvocationTokenReadField |
+| SkillInvocationTokenReadTokenTypeField |
+| SkillInvocationTokenWriteField |
+| SkillInvocationTokenWriteTokenTypeField |
+| SkillInvocationTypeField |
+| WebhookInvocation |
+| WebhookInvocationTriggerField |
+| WebhookInvocationTypeField |
+| WorkflowFull |
+
+If your code references any of these types, remove those references.
diff --git a/migration-guides/from-v4-to-v10.md b/migration-guides/from-v4-to-v10.md
new file mode 100644
index 000000000..a38d4f5de
--- /dev/null
+++ b/migration-guides/from-v4-to-v10.md
@@ -0,0 +1,691 @@
+# Migration guide from v4 to v10 version of `box-java-sdk`
+
+
+
+
+- [Introduction](#introduction)
+- [Installation](#installation)
+ - [Maven](#maven)
+ - [Gradle](#gradle)
+- [Key differences](#key-differences)
+ - [Manager approach](#manager-approach)
+ - [Immutable design](#immutable-design)
+ - [Consistent method signature](#consistent-method-signature)
+- [Authentication](#authentication)
+ - [Developer Token](#developer-token)
+ - [JWT Auth](#jwt-auth)
+ - [Using JWT configuration file](#using-jwt-configuration-file)
+ - [Providing JWT configuration manually](#providing-jwt-configuration-manually)
+ - [Authenticate user](#authenticate-user)
+ - [Client Credentials Grant](#client-credentials-grant)
+ - [Obtaining Service Account token](#obtaining-service-account-token)
+ - [Obtaining User token](#obtaining-user-token)
+ - [Switching between Service Account and User](#switching-between-service-account-and-user)
+ - [OAuth 2.0 Auth](#oauth-20-auth)
+ - [Get Authorization URL](#get-authorization-url)
+ - [Authenticate](#authenticate)
+ - [Store token and retrieve token callbacks](#store-token-and-retrieve-token-callbacks)
+ - [Downscope token](#downscope-token)
+ - [Revoke token](#revoke-token)
+- [Configuration](#configuration)
+ - [As-User header](#as-user-header)
+ - [Custom Base URLs](#custom-base-urls)
+- [Convenience methods](#convenience-methods)
+ - [Webhook validation](#webhook-validation)
+ - [Chunked upload of big files](#chunked-upload-of-big-files)
+
+
+
+## Introduction
+
+The v10 release of `box-java-sdk` library helps Java developers to conveniently integrate with Box API.
+In the contrary to the previous versions (v4 or lower), it is not manually maintained, but auto-generated
+based on Open API Specification. This means you can leverage the most up-to-date Box API features in your
+applications without delay. We introduced this major version bump to reflect the significant codebase changes
+and to align with other Box SDKs, which will also adopt generated code starting from their v10 releases.
+More information and benefits of using the new can be found in the
+[README](https://github.com/box/box-java-sdk/blob/sdk-gen/README.md) file.
+
+## Installation
+
+To install v10 version of Box Java SDK, you can use Maven or Gradle. The library is available in the
+[Maven Central Repository](https://search.maven.org/artifact/com.box/box-java-sdk).
+
+Soon we are going to introduce v5 version of Box Java SDK that will combine package `com.box.sdk` from
+v4 and `com.box.sdkgen` from v10 of the SDK so that code from both versions could be used in the same project.
+If you would like to use a feature available only in the new SDK, you won't need to necessarily migrate all your code
+to use generated SDK at once. You will be able to use a new feature from the `com.box.sdkgen` package,
+while keeping the rest of your code unchanged. Note that it may be required to use fully qualified class names
+to avoid conflicts between two packages. However, we recommend to fully migrate to the v10 of the SDK eventually.
+
+### Maven
+
+To start using generated version of the SDK in you Maven project just bump the version of the Box Java SDK library
+in `pom.xml`to 10.0.0 or higher:
+
+```xml
+
+ com.box
+ box-java-sdk
+ 10.0.0
+
+```
+
+### Gradle
+
+To bump a dependency in your Gradle project, bump the version useed in your `build.gradle` file:
+
+```groovy
+implementation 'com.box:box-java-sdk:10.0.0'
+```
+
+## Key differences
+
+### Manager approach
+
+The main difference between the manual v4 version of the SDK and the nextgen generated one,
+is the way how API methods are aggregated into objects.
+
+**Old (`v4`)**
+
+Firstly, in the v4 version of the SDK to be able to perform any action on an API object, e.g. `User`, you first had to create its class.
+To do it is required to call:
+
+```java
+BoxUser user = new BoxUser(api, "12345");
+```
+
+to create a class representing an already existing User with id '12345', or create a new one with a call:
+
+```java
+BoxUser.Info createdUserInfo = BoxUser.createAppUser(api, "A User");
+BoxUser user = new BoxUser(api, createdUserInfo.getID());
+```
+
+Then, you could perform any action on created class, which will affect the user, e.g.
+
+```java
+BoxUser.Info info = user.new Info();
+info.setName(name);
+user.updateInfo(info);
+```
+
+**New (`v10`)**
+
+In the v10 version of the SDK the API methods are grouped into dedicated manager classes, e.g. `User` object
+has dedicated `UserManager` class. Each manager class instance is available in `BoxClient` object.
+The fields storing references to the managers are named in the plural form of the resource that the
+manager handles - `client.users` for `UsersManager`. If you want to perform any operation
+connected with a `User` you need to call a respective method of `UserManager`.
+For example, to get info about existing user you need to call:
+
+```java
+UserFull user = client.users.getUsersById("12345");
+```
+
+or to create a new user:
+
+```java
+CreateUserRequestBody requestBody =
+ new CreateUserRequestBody.Builder("John Doe").build();
+UserFull user = client.users.createUser(requestBody);
+```
+
+The `UserFull` object returned by both of these methods is a data class - it does not contain any methods to call.
+To perform any action on `User` object, you need to still use a `UserManager` method for that.
+Usually these methods have a first argument, which accepts id of the object you want to access,
+e.g. to update a user name, call method:
+
+```java
+UpdateUserByIdRequestBody requestBody =
+ new UpdateUserByIdRequestBody.Builder().name("Mary").build();
+UserFull updatedUser = client.users.updateUserById(user.getId(), requestBody);
+```
+
+### Immutable design
+
+The v10 is designed to be mostly immutable. This means that methods,
+which used to modify the existing object in v4 release now return a new instance of the class with the modified state.
+This design pattern is used to avoid side effects and make the code more predictable and easier to reason about.
+Methods, which returns a new modified instance of an object, will always have a prefix `with` in their names, e.g.
+
+**New (`v10`)**
+
+```java
+BoxClient client = new BoxClient(auth);
+BoxClient asUserClient = client.withAsUserHeader("USER_ID");
+```
+
+### Consistent method signature
+
+To facilitate easier work with the new SDK, we have changed the API method signatures to be consistent and unified.
+
+**Old (`v4`)**
+
+In the manual version, API methods had numerous parameters, which were not grouped into any objects and were passed as separate arguments, e.g. the method for creating a sign request looked like this:
+
+```java
+public static BoxSignRequest.Info createSignRequest(BoxAPIConnection api, List sourceFiles,
+ List signers, String parentFolderId,
+ BoxSignRequestCreateParams optionalParams)
+```
+
+**New (`v10`)**
+
+In the v10, we have adopted an approach of aggregating parameters into types based on their nature (path, body, query, headers).
+This can be seen in the example corresponding to the above:
+
+```java
+public SignRequest createSignRequest(
+ SignRequestCreateRequest requestBody, CreateSignRequestHeaders headers)
+```
+
+According to the convention, if an API endpoint requires a parameter placed in the URL path, it will appear at the beginning of our method, such as `fileId` in this case. When a request allows for a body, as in `POST` or `PUT`, the method includes a parameter named `requestBody`. Following that, the method signature may include the `queryParams` parameter, followed by `headers`.
+
+The types of parameters `requestBody`, `queryParams`, and `headers` are specific to each endpoint and, in their definition, encompass all fields allowed by the API.
+
+It's worth noting here that when all fields of a particular type are optional, the entire parameter becomes optional as well. This allows us to pass only the parameters we actually want to provide when calling a given method, without the risk of not providing a sufficient number of parameters.
+
+## Authentication
+
+The v10 release of Box Java SDK library offers the same authentication methods as the v4 one.
+Let's see the differences of their usage:
+
+### Developer Token
+
+**Old (`v4`)**
+
+```java
+BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN");
+```
+
+The v10 release provides a convenient `BoxDeveloperTokenAuth`, which allows authenticating
+using developer token without necessity to provide a Client ID and Client Secret
+
+**New (`v10`)**
+
+```java
+BoxDeveloperTokenAuth auth = new BoxDeveloperTokenAuth("YOUR-DEVELOPER-TOKEN");
+BoxClient client = new BoxClient(auth);
+```
+
+### JWT Auth
+
+#### Using JWT configuration file
+
+**Old (`v4`)**
+
+The static method, which reads the JWT configuration file has been changed:
+
+```java
+Reader reader = new FileReader("src/example/config/config.json");
+BoxConfig boxConfig = BoxConfig.readFrom(reader);
+IAccessTokenCache tokenCache = new InMemoryLRUAccessTokenCache(100);
+BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(boxConfig, tokenCache);
+```
+
+**New (`v10`)**
+
+```java
+TokenStorage tokenStorage = new InMemoryTokenStorage(); // or any other implementation of TokenStorage
+JWTConfig config = JWTConfig.fromConfigFile("src/example/config/config.json", tokenStorage);
+BoxJWTAuth auth = new BoxJWTAuth(config);
+BoxClient client = new BoxClient(auth);
+```
+
+#### Providing JWT configuration manually
+
+Some params in `JWTConfig` constructor have slightly different names than one in old `JWTAuth` class.
+
+**Old (`v4`)**
+
+```java
+JWTEncryptionPreferences jwtPreferences = new JWTEncryptionPreferences();
+jwtPreferences.setPublicKeyID("PUBLIC-KEY-ID");
+jwtPreferences.setPrivateKeyPassword("PRIVATE-KEY-PASSWORD");
+jwtPreferences.setPrivateKey("PRIVATE-KEY");
+jwtPreferences.setEncryptionAlgorithm(EncryptionAlgorithm.RSA_SHA_256);
+
+IAccessTokenCache accessTokenCache = new InMemoryLRUAccessTokenCache(100);
+BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection
+ .getUserConnection("USER-ID", "CLIENT-ID","CLIENT-SECRET", jwtPreferences, accessTokenCache);
+
+BoxUser.Info userInfo = BoxUser.getCurrentUser(api).getInfo();
+```
+
+**New (`v10`)**
+
+```java
+TokenStorage tokenStorage = new InMemoryTokenStorage();
+JWTConfig config = new JWTConfig.Builder("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "JWT_KEY_ID", "PRIVATE_KEY", "PRIVATE_KEY_PASSWORD")
+ .enterpriseId("123456")
+ .tokenStorage(tokenStorage)
+ .build();
+BoxJWTAuth auth = new BoxJWTAuth(config);
+BoxClient client = new BoxClient(auth);
+```
+
+#### Authenticate user
+
+In v4 release method for user authentication was named `BoxDeveloperEditionAPIConnection getUserConnection(String userId, BoxConfig boxConfig, IAccessTokenCache accessTokenCache)`
+and was accepting user id. The method was returning a new instance of `BoxDeveloperEditionAPIConnection` class, which was exchanging the existing token with the one with the user access.
+
+**Old (`v4`)**
+
+```java
+BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getUserConnection("USER_ID", boxConfig, tokenCache);
+```
+
+**New (`v10`)**
+
+In v10, to authenticate as user you need to call
+`public BoxJWTAuth withUserSubject(String userId, TokenStorage tokenStorage)` method with id of the user
+to authenticate. The method returns a new instance of `BoxJWTAuth` class, which will perform authentication call
+in scope of the user on the first API call. The `tokenStorage` parameter is optional and allows to provide a custom
+token storage for the new instance of `BoxJWTAuth` class. The new auth instance can be used to create a new user client
+instance.
+
+```java
+BoxJWTAuth userAuth = auth.withUserSubject("USER_ID");
+BoxClient userClient = new BoxClient(userAuth);
+```
+
+### Client Credentials Grant
+
+#### Obtaining Service Account token
+
+To authenticate as enterprise, the only difference between the v4 and v10 is using the `CCGConfig` as a middle step.
+
+**Old (`v4`)**
+
+```java
+BoxCCGAPIConnection api = BoxCCGAPIConnection.applicationServiceAccountConnection(
+ "client_id",
+ "client_secret",
+ "enterprise_id"
+);
+```
+
+**New (`v10`)**
+
+```java
+CCGConfig config = new CCGConfig.Builder("YOUR_CLIENT", "YOUR_CLIENT_SECRET")
+ .enterpriseId("ENTERPRISE_ID")
+ .build();
+BoxCCGAuth auth = new BoxCCGAuth(config);
+BoxClient client = new BoxClient(auth);
+```
+
+#### Obtaining User token
+
+To authenticate as user, the only difference between the versions is using the `CCGConfig` as a middle step.
+
+**Old (`v4`)**
+
+```java
+BoxCCGAPIConnection api = BoxCCGAPIConnection.userConnection(
+ "client_id",
+ "client_secret",
+ "user_id"
+);
+```
+
+**New (`v10`)**
+
+```java
+CCGConfig config = new CCGConfig.Builder("YOUR_CLIENT", "YOUR_CLIENT_SECRET")
+ .userId("USER_ID")
+ .build();
+BoxCCGAuth auth = new BoxCCGAuth(config);
+BoxClient client = new BoxClient(auth);
+```
+
+### Switching between Service Account and User
+
+In v4 release, if you want to switch between the Service Account and User, you need to create another API connection.
+
+In the v10, to keep the immutability design, the methods switching authenticated subject were replaced with methods
+returning a new instance of `BoxCCGAuth` class. The new instance will fetch a new token on the next API call.
+The new auth instance can be used to create a new client instance. You can also specify `tokenStorage` parameter
+to provide a custom token storage for the new instance.
+The old instance of `BoxCCGAuth` class will remain unchanged and will still use the old token.
+
+**New (`v10`)**
+
+```java
+BoxCCGAuth userAuth = auth.withUserSubject("USER_ID");
+BoxClient userClient = new BoxClient(userAuth);
+```
+
+```java
+BoxCCGAuth entAuth = auth.withEnterpriseSubject("ENTERPRISE_ID");
+BoxClient entClient = new BoxClient(entAuth);
+```
+
+### OAuth 2.0 Auth
+
+#### Get Authorization URL
+
+To get authorization url in the v10 release, you need to first create the `BoxOAuth` class using
+`OAuthConfig` class. Then to get authorization url, call
+`public String getAuthorizeUrl(GetAuthorizeUrlOptions options)`. Note that this method accepts the instance of `GetAuthorizeUrlOptions` class, which allows specifying extra options to API call.
+
+**Old (`v4`)**
+
+In the v4, we did not have any method to get the authorization URL. Instead, we had to manually create the URL.
+
+```java
+String authorizationUrl = "https://account.box.com/api/oauth2/authorize?client_id=[CLIENT_ID]&response_type=code";
+```
+
+**New (`v10`)**
+
+```java
+BoxOAuth auth = new BoxOAuth(new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET").build());
+String authorizationUrl = auth.getAuthorizeUrl();
+```
+
+#### Authenticate
+
+The method for authenticating using the authorization code has been changed. With the v4 version of the SDK,
+you had to provide the authorization code to the `BoxAPIConnection` class constructor. In the v10 version,
+you need to call the `public AccessToken getTokensAuthorizationCodeGrant(String authorizationCode)` method of the `BoxOAuth` class.
+The method now returns an AccessToken object with `accessToken` and `refreshToken` fields,
+while the old one was creating a new instance of `BoxAPIConnection` class.
+
+**Old (`v4`)**
+
+```java
+BoxAPIConnection client = new BoxAPIConnection(
+ "[CLIENT_ID]",
+ "[CLIENT_SECRET]",
+ "[CODE]"
+);
+```
+
+**New (`v10`)**
+
+```java
+auth.getTokensAuthorizationCodeGrant("AUTHORIZATION_CODE");
+BoxClient client = new BoxClient(auth);
+```
+
+### Store token and retrieve token callbacks
+
+In the v10 release you can define your own class delegated for storing and retrieving a token. It has to inherit from
+`TokenStorage` and implement all of its abstract methods. Next step would be to pass an instance of this class to the
+AuthConfig constructor.
+
+**New (`v10`)**
+
+```java
+TokenStorage customTokenStorage = new TokenStorage() {
+ @Override
+ public void store(AccessToken accessToken) {
+ // Store the access token
+ }
+
+ @Override
+ public AccessToken get() {
+ // Retrieve the access token
+ return null;
+ }
+
+ @Override
+ public void clear() {
+ // Clear the access token
+ }
+};
+
+OAuthConfig config = new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET")
+ .tokenStorage(customTokenStorage)
+ .build();
+BoxOAuth auth = new BoxOAuth(config);
+```
+
+or reuse one of the provided implementations: `InMemoryTokenStorage`:
+
+```java
+TokenStorage tokenStorage = new InMemoryTokenStorage();
+OAuthConfig config = new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET")
+ .tokenStorage(tokenStorage)
+ .build();
+BoxOAuth auth = new BoxOAuth(config);
+```
+
+### Downscope token
+
+The process of downscoping token in the new version is similar to the old one. The main difference is that in the new version
+you need to call `downscopeToken` method of the `BoxOAuth` class instead of `getLowerScopedToken` method of the `BoxAPIConnection` class.
+
+**Old (`v4`)**
+
+```java
+BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN");
+
+String resource = "https://api.box.com/2.0/files/RESOURCE-ID";
+List scopes = new ArrayList();
+scopes.add("item_preview");
+scopes.add("item_content_upload");
+
+ScopedToken token = api.getLowerScopedToken(scopes, resource);
+```
+
+**New (`v10`)**
+
+```java
+String resource = "https://api.box.com/2.0/files/123456789";
+List scopes = List.of("item_preview");
+AccessToken downscopedToken = auth.downscopeToken(scopes, resource, null, null);
+BoxDeveloperTokenAuth downscopedAuth = new BoxDeveloperTokenAuth(downscopedToken.getAccessToken());
+BoxClient downscopedClient = new BoxClient(downscopedAuth);
+```
+
+### Revoke token
+
+To revoke current client's tokens in the v10 release, you need to call `revokeToken` method of the auth class instead of
+`revoke` method.
+
+**Old (`v4`)**
+
+```java
+BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN");
+api.revokeToken();
+```
+
+**New (`v10`)**
+
+```java
+client.auth.revokeToken()
+```
+
+## Configuration
+
+### As-User header
+
+The As-User header is used by enterprise admins to make API calls on behalf of their enterprise's users.
+This requires the API request to pass an `As-User: USER-ID` header. The following examples assume that the client has
+been instantiated with an access token with appropriate privileges to make As-User calls.
+
+In v4 release you could call client `asUser(String userID)` method to create a new client to impersonate the provided user.
+
+**Old (`v4`)**
+
+```java
+BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN");
+api.asUser("USER-ID");
+```
+
+**New (`v10`)**
+
+In the new version, the method was renamed to `withAsUserHeader` in the `BoxClient` class,
+and returns a new instance of `BoxClient` class with the As-User header appended to all API calls made by the client.
+The method accepts only user id as a parameter.
+
+```java
+BoxClient userClient = client.withAsUserHeader("USER-ID");
+```
+
+Additionally `BoxClient` offers a `withExtraHeaders(Map extraHeaders)`
+method, which allows you to specify the custom set of headers, which will be included in every API call made by client.
+Calling the `client.withExtraHeaders()` method creates a new client, leaving the original client unmodified.
+
+```java
+BoxClient clientWithExtraHeaders = client.withExtraHeaders(new HashMap<>() {{
+ put("X-My-Header", "124");
+}});
+
+```
+
+### Custom Base URLs
+
+**Old (`v4`)**
+
+In v4 you could specify the custom base URLs, which will be used for API calls made by setting
+the new values of static variables of the `API` class.
+
+```java
+BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN");
+api.setBaseAppUrl("https://example.app.com");
+api.setBaseURL("https://example.com");
+api.setUploadURL("https://upload.example.com");
+api.setTokenURL("https://example.com/token");
+```
+
+**New (`v10`)**
+
+Inv10 this functionality has been implemented as part of the `BoxClient` class.
+By calling the `client.withCustomBaseUrls()` method, you can specify the custom base URLs that will be used for API
+calls made by client. Following the immutability pattern, this call creates a new client, leaving the original client unmodified.
+
+```java
+BaseUrls baseUrls = new BaseUrls.Builder()
+ .baseUrl("https://new-base-url.com")
+ .uploadUrl("https://my-company-upload-url.com")
+ .oauth2Url("https://my-company.com/oauth2")
+ .build();
+BoxClient clientWithCustomBaseUrl = client.withCustomBaseUrls(baseUrls);
+```
+
+## Convenience methods
+
+### Webhook validation
+
+Webhook validation is used to validate a webhook message by verifying the signature and the delivery timestamp.
+
+**Old (`v4`)**
+
+In v4, when you receive a webhook message from Box, to validate that it actually came from Box
+you need to call `BoxWebHookSignatureVerifier#verify(String sigVersion, String sigAlgorithm, String primarySignature, String secondarySignature, String payload, String deliveryTimestamp)` method.
+It would return a `boolean` value indicating whether the message was valid.
+
+```java
+// Webhook message contents are shown for demonstration purposes
+// Normally these would come from your HTTP handler
+
+// Webhook message HTTP body
+String messagePayload = "{"
++ "\"type\":\"webhook_event","
++ "\"webhook\":{"
++ "\"id\":\"1234567890\""
++ "},"
++ "\"trigger\":\"FILE.UPLOADED\","
++ "\"source\":{"
++ "\"id\":\"1234567890\","
++ "\"type\":\"file\","
++ "\"name\":\"Test.txt\""
++ "}}";
+
+// Webhook message HTTP headers
+Map messageHeaders = new HashMap();
+headers.put("BOX-DELIVERY-ID", "f96bb54b-ee16-4fc5-aa65-8c2d9e5b546f");
+headers.put("BOX-DELIVERY-TIMESTAMP", "2020-01-01T00:00:00-07:00");
+headers.put("BOX-SIGNATURE-ALGORITHM", "HmacSHA256");
+headers.put("BOX-SIGNATURE-PRIMARY", "6TfeAW3A1PASkgboxxA5yqHNKOwFyMWuEXny/FPD5hI=");
+headers.put("BOX-SIGNATURE-SECONDARY", "v+1CD1Jdo3muIcbpv5lxxgPglOqMfsNHPV899xWYydo=");
+headers.put("BOX-SIGNATURE-VERSION", "1");
+
+// Your application's webhook keys, obtained from the Box Developer Console
+String primaryKey = "4py2I9eSFb0ezXH5iPeQRcFK1LRLCdip";
+String secondaryKey = "Aq5EEEjAu4ssbz8n9UMu7EerI0LKj2TL";
+
+BoxWebHookSignatureVerifier verifier = new BoxWebHookSignatureVerifier(primaryKey, secondaryKey);
+boolean isValidMessage = verifier.verify(
+ headers.get("BOX-SIGNATURE-VERSION"),
+ headers.get("BOX-SIGNATURE-ALGORITHM"),
+ headers.get("BOX-SIGNATURE-PRIMARY"),
+ headers.get("BOX-SIGNATURE-SECONDARY"),
+ messagePayload,
+ headers.get("BOX-DELIVERY-TIMESTAMP")
+);
+```
+
+**New (`v10`)**
+
+In the v10 version of ths SDK, the `WebhooksManager.validateMessage()` method requires the `messagePayload` to be of type `string`,
+map of headers to be of type `Map`, and the primary and secondary keys to be of type `String`.
+
+```java
+// Webhook message HTTP body
+String messagePayload = "{"
+ + "\"type\":\"webhook_event","
+ + "\"webhook\":{"
+ + "\"id\":\"1234567890\""
+ + "},"
+ + "\"trigger\":\"FILE.UPLOADED\","
+ + "\"source\":{"
+ + "\"id\":\"1234567890\","
+ + "\"type\":\"file\","
+ + "\"name\":\"Test.txt\""
+ + "}}";
+
+// Webhook message HTTP headers
+Map messageHeaders = new HashMap();
+headers.put("BOX-DELIVERY-ID", "f96bb54b-ee16-4fc5-aa65-8c2d9e5b546f");
+headers.put("BOX-DELIVERY-TIMESTAMP", "2020-01-01T00:00:00-07:00");
+headers.put("BOX-SIGNATURE-ALGORITHM", "HmacSHA256");
+headers.put("BOX-SIGNATURE-PRIMARY", "6TfeAW3A1PASkgboxxA5yqHNKOwFyMWuEXny/FPD5hI=");
+headers.put("BOX-SIGNATURE-SECONDARY", "v+1CD1Jdo3muIcbpv5lxxgPglOqMfsNHPV899xWYydo=");
+headers.put("BOX-SIGNATURE-VERSION", "1");
+
+// Your application's webhook keys, obtained from the Box Developer Console
+String primaryKey = "4py2I9eSFb0ezXH5iPeQRcFK1LRLCdip";
+String secondaryKey = "Aq5EEEjAu4ssbz8n9UMu7EerI0LKj2TL";
+
+boolean isValidMessage = WebhooksManager.validateMessage(
+ messagePayload, messageHeaders, primaryKey, secondaryKey);
+)
+```
+
+### Chunked upload of big files
+
+For large files or in cases where the network connection is less reliable, you may want to upload the file in parts.
+This allows a single part to fail without aborting the entire upload, and failed parts are being retried automatically.
+
+**Old (`v4`)**
+
+In the v4, you could use the `uploadLargeFile` method of the `BoxFolder` class to upload a large file.
+This method accepted a `FileInputStream` as the input stream and the file size as a parameter. The method also required
+
+```java
+File myFile = new File("My Large_File.txt");
+FileInputStream stream = new FileInputStream(myFile);
+
+BoxFolder rootFolder = BoxFolder.getRootFolder(api);
+BoxFile.Info fileInfo = rootFolder.uploadLargeFile(inputStream, "My_Large_File.txt", myFile.length());
+```
+
+**New (`v10`)**
+
+In the v10, the equivalent method is `chunked_uploads.uploadBigFile()`. It accepts a file-like object
+as the `file` parameter, and the `fileName` and `fileSize` parameters are now passed as arguments.
+The `parentFolderId` parameter is also required to specify the folder where the file will be uploaded.
+
+```java
+InputStream file = new FileInputStream(myFile);
+String fileName = "My_Large_File.txt";
+long fileSize = 1234556L;
+String parentFolderId = "123456789";
+
+File uploadedFile = client.getChunkedUploads().uploadBigFile(file, fileName, fileSize, parentFolderId);
+```