diff --git a/homeassistant/components/onedrive/__init__.py b/homeassistant/components/onedrive/__init__.py
index 4ae5ac7356044e77afc11463794a48fc98f50cea..ef7ddd04da62da120d2de4c0a18ba8824c73983c 100644
--- a/homeassistant/components/onedrive/__init__.py
+++ b/homeassistant/components/onedrive/__init__.py
@@ -5,34 +5,33 @@ from __future__ import annotations
 from dataclasses import dataclass
 import logging
 
-from kiota_abstractions.api_error import APIError
-from kiota_abstractions.authentication import BaseBearerTokenAuthenticationProvider
-from msgraph import GraphRequestAdapter, GraphServiceClient
-from msgraph.generated.drives.item.items.items_request_builder import (
-    ItemsRequestBuilder,
+from onedrive_personal_sdk import OneDriveClient
+from onedrive_personal_sdk.exceptions import (
+    AuthenticationError,
+    HttpRequestException,
+    OneDriveException,
 )
-from msgraph.generated.models.drive_item import DriveItem
-from msgraph.generated.models.folder import Folder
 
 from homeassistant.config_entries import ConfigEntry
 from homeassistant.core import HomeAssistant, callback
 from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
+from homeassistant.helpers.aiohttp_client import async_get_clientsession
 from homeassistant.helpers.config_entry_oauth2_flow import (
     OAuth2Session,
     async_get_config_entry_implementation,
 )
-from homeassistant.helpers.httpx_client import create_async_httpx_client
 from homeassistant.helpers.instance_id import async_get as async_get_instance_id
 
 from .api import OneDriveConfigEntryAccessTokenProvider
-from .const import DATA_BACKUP_AGENT_LISTENERS, DOMAIN, OAUTH_SCOPES
+from .const import DATA_BACKUP_AGENT_LISTENERS, DOMAIN
 
 
 @dataclass
 class OneDriveRuntimeData:
     """Runtime data for the OneDrive integration."""
 
-    items: ItemsRequestBuilder
+    client: OneDriveClient
+    token_provider: OneDriveConfigEntryAccessTokenProvider
     backup_folder_id: str
 
 
@@ -47,29 +46,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: OneDriveConfigEntry) ->
 
     session = OAuth2Session(hass, entry, implementation)
 
-    auth_provider = BaseBearerTokenAuthenticationProvider(
-        access_token_provider=OneDriveConfigEntryAccessTokenProvider(session)
-    )
-    adapter = GraphRequestAdapter(
-        auth_provider=auth_provider,
-        client=create_async_httpx_client(hass, follow_redirects=True),
-    )
+    token_provider = OneDriveConfigEntryAccessTokenProvider(session)
 
-    graph_client = GraphServiceClient(
-        request_adapter=adapter,
-        scopes=OAUTH_SCOPES,
-    )
-    assert entry.unique_id
-    drive_item = graph_client.drives.by_drive_id(entry.unique_id)
+    client = OneDriveClient(token_provider, async_get_clientsession(hass))
 
     # get approot, will be created automatically if it does not exist
     try:
-        approot = await drive_item.special.by_drive_item_id("approot").get()
-    except APIError as err:
-        if err.response_status_code == 403:
-            raise ConfigEntryAuthFailed(
-                translation_domain=DOMAIN, translation_key="authentication_failed"
-            ) from err
+        approot = await client.get_approot()
+    except AuthenticationError as err:
+        raise ConfigEntryAuthFailed(
+            translation_domain=DOMAIN, translation_key="authentication_failed"
+        ) from err
+    except (HttpRequestException, OneDriveException, TimeoutError) as err:
         _LOGGER.debug("Failed to get approot", exc_info=True)
         raise ConfigEntryNotReady(
             translation_domain=DOMAIN,
@@ -77,24 +65,24 @@ async def async_setup_entry(hass: HomeAssistant, entry: OneDriveConfigEntry) ->
             translation_placeholders={"folder": "approot"},
         ) from err
 
-    if approot is None or not approot.id:
-        _LOGGER.debug("Failed to get approot, was None")
+    instance_id = await async_get_instance_id(hass)
+    backup_folder_name = f"backups_{instance_id[:8]}"
+    try:
+        backup_folder = await client.create_folder(
+            parent_id=approot.id, name=backup_folder_name
+        )
+    except (HttpRequestException, OneDriveException, TimeoutError) as err:
+        _LOGGER.debug("Failed to create backup folder", exc_info=True)
         raise ConfigEntryNotReady(
             translation_domain=DOMAIN,
             translation_key="failed_to_get_folder",
-            translation_placeholders={"folder": "approot"},
-        )
-
-    instance_id = await async_get_instance_id(hass)
-    backup_folder_id = await _async_create_folder_if_not_exists(
-        items=drive_item.items,
-        base_folder_id=approot.id,
-        folder=f"backups_{instance_id[:8]}",
-    )
+            translation_placeholders={"folder": backup_folder_name},
+        ) from err
 
     entry.runtime_data = OneDriveRuntimeData(
-        items=drive_item.items,
-        backup_folder_id=backup_folder_id,
+        client=client,
+        token_provider=token_provider,
+        backup_folder_id=backup_folder.id,
     )
 
     _async_notify_backup_listeners_soon(hass)
@@ -116,54 +104,3 @@ def _async_notify_backup_listeners(hass: HomeAssistant) -> None:
 @callback
 def _async_notify_backup_listeners_soon(hass: HomeAssistant) -> None:
     hass.loop.call_soon(_async_notify_backup_listeners, hass)
-
-
-async def _async_create_folder_if_not_exists(
-    items: ItemsRequestBuilder,
-    base_folder_id: str,
-    folder: str,
-) -> str:
-    """Check if a folder exists and create it if it does not exist."""
-    folder_item: DriveItem | None = None
-
-    try:
-        folder_item = await items.by_drive_item_id(f"{base_folder_id}:/{folder}:").get()
-    except APIError as err:
-        if err.response_status_code != 404:
-            _LOGGER.debug("Failed to get folder %s", folder, exc_info=True)
-            raise ConfigEntryNotReady(
-                translation_domain=DOMAIN,
-                translation_key="failed_to_get_folder",
-                translation_placeholders={"folder": folder},
-            ) from err
-        # is 404 not found, create folder
-        _LOGGER.debug("Creating folder %s", folder)
-        request_body = DriveItem(
-            name=folder,
-            folder=Folder(),
-            additional_data={
-                "@microsoft_graph_conflict_behavior": "fail",
-            },
-        )
-        try:
-            folder_item = await items.by_drive_item_id(base_folder_id).children.post(
-                request_body
-            )
-        except APIError as create_err:
-            _LOGGER.debug("Failed to create folder %s", folder, exc_info=True)
-            raise ConfigEntryNotReady(
-                translation_domain=DOMAIN,
-                translation_key="failed_to_create_folder",
-                translation_placeholders={"folder": folder},
-            ) from create_err
-        _LOGGER.debug("Created folder %s", folder)
-    else:
-        _LOGGER.debug("Found folder %s", folder)
-    if folder_item is None or not folder_item.id:
-        _LOGGER.debug("Failed to get folder %s, was None", folder)
-        raise ConfigEntryNotReady(
-            translation_domain=DOMAIN,
-            translation_key="failed_to_get_folder",
-            translation_placeholders={"folder": folder},
-        )
-    return folder_item.id
diff --git a/homeassistant/components/onedrive/api.py b/homeassistant/components/onedrive/api.py
index 934a4f74ec90e7c0f133b87a373c53d9f60587a6..d8f6ea188f39aed3b8d635cdabce9ca9a802a4d1 100644
--- a/homeassistant/components/onedrive/api.py
+++ b/homeassistant/components/onedrive/api.py
@@ -1,28 +1,14 @@
 """API for OneDrive bound to Home Assistant OAuth."""
 
-from typing import Any, cast
+from typing import cast
 
-from kiota_abstractions.authentication import AccessTokenProvider, AllowedHostsValidator
+from onedrive_personal_sdk import TokenProvider
 
 from homeassistant.const import CONF_ACCESS_TOKEN
 from homeassistant.helpers import config_entry_oauth2_flow
 
 
-class OneDriveAccessTokenProvider(AccessTokenProvider):
-    """Provide OneDrive authentication tied to an OAuth2 based config entry."""
-
-    def __init__(self) -> None:
-        """Initialize OneDrive auth."""
-        super().__init__()
-        # currently allowing all hosts
-        self._allowed_hosts_validator = AllowedHostsValidator(allowed_hosts=[])
-
-    def get_allowed_hosts_validator(self) -> AllowedHostsValidator:
-        """Retrieve the allowed hosts validator."""
-        return self._allowed_hosts_validator
-
-
-class OneDriveConfigFlowAccessTokenProvider(OneDriveAccessTokenProvider):
+class OneDriveConfigFlowAccessTokenProvider(TokenProvider):
     """Provide OneDrive authentication tied to an OAuth2 based config entry."""
 
     def __init__(self, token: str) -> None:
@@ -30,14 +16,12 @@ class OneDriveConfigFlowAccessTokenProvider(OneDriveAccessTokenProvider):
         super().__init__()
         self._token = token
 
-    async def get_authorization_token(  # pylint: disable=dangerous-default-value
-        self, uri: str, additional_authentication_context: dict[str, Any] = {}
-    ) -> str:
-        """Return a valid authorization token."""
+    def async_get_access_token(self) -> str:
+        """Return a valid access token."""
         return self._token
 
 
-class OneDriveConfigEntryAccessTokenProvider(OneDriveAccessTokenProvider):
+class OneDriveConfigEntryAccessTokenProvider(TokenProvider):
     """Provide OneDrive authentication tied to an OAuth2 based config entry."""
 
     def __init__(self, oauth_session: config_entry_oauth2_flow.OAuth2Session) -> None:
@@ -45,9 +29,6 @@ class OneDriveConfigEntryAccessTokenProvider(OneDriveAccessTokenProvider):
         super().__init__()
         self._oauth_session = oauth_session
 
-    async def get_authorization_token(  # pylint: disable=dangerous-default-value
-        self, uri: str, additional_authentication_context: dict[str, Any] = {}
-    ) -> str:
-        """Return a valid authorization token."""
-        await self._oauth_session.async_ensure_token_valid()
+    def async_get_access_token(self) -> str:
+        """Return a valid access token."""
         return cast(str, self._oauth_session.token[CONF_ACCESS_TOKEN])
diff --git a/homeassistant/components/onedrive/backup.py b/homeassistant/components/onedrive/backup.py
index a7bac5d01fc36a01c4933a560841236d1c1b63c2..43eac020538da0eb7ff76bca98acbcf19b2c331e 100644
--- a/homeassistant/components/onedrive/backup.py
+++ b/homeassistant/components/onedrive/backup.py
@@ -2,37 +2,22 @@
 
 from __future__ import annotations
 
-import asyncio
 from collections.abc import AsyncIterator, Callable, Coroutine
 from functools import wraps
 import html
 import json
 import logging
-from typing import Any, Concatenate, cast
-
-from httpx import Response, TimeoutException
-from kiota_abstractions.api_error import APIError
-from kiota_abstractions.authentication import AnonymousAuthenticationProvider
-from kiota_abstractions.headers_collection import HeadersCollection
-from kiota_abstractions.method import Method
-from kiota_abstractions.native_response_handler import NativeResponseHandler
-from kiota_abstractions.request_information import RequestInformation
-from kiota_http.middleware.options import ResponseHandlerOption
-from msgraph import GraphRequestAdapter
-from msgraph.generated.drives.item.items.item.content.content_request_builder import (
-    ContentRequestBuilder,
-)
-from msgraph.generated.drives.item.items.item.create_upload_session.create_upload_session_post_request_body import (
-    CreateUploadSessionPostRequestBody,
-)
-from msgraph.generated.drives.item.items.item.drive_item_item_request_builder import (
-    DriveItemItemRequestBuilder,
-)
-from msgraph.generated.models.drive_item import DriveItem
-from msgraph.generated.models.drive_item_uploadable_properties import (
-    DriveItemUploadableProperties,
+from typing import Any, Concatenate
+
+from aiohttp import ClientTimeout
+from onedrive_personal_sdk.clients.large_file_upload import LargeFileUploadClient
+from onedrive_personal_sdk.exceptions import (
+    AuthenticationError,
+    HashMismatchError,
+    OneDriveException,
 )
-from msgraph_core.models import LargeFileUploadSession
+from onedrive_personal_sdk.models.items import File, Folder, ItemUpdate
+from onedrive_personal_sdk.models.upload import FileInfo
 
 from homeassistant.components.backup import (
     AgentBackup,
@@ -41,14 +26,14 @@ from homeassistant.components.backup import (
     suggested_filename,
 )
 from homeassistant.core import HomeAssistant, callback
-from homeassistant.helpers.httpx_client import get_async_client
+from homeassistant.helpers.aiohttp_client import async_get_clientsession
 
 from . import OneDriveConfigEntry
 from .const import DATA_BACKUP_AGENT_LISTENERS, DOMAIN
 
 _LOGGER = logging.getLogger(__name__)
 UPLOAD_CHUNK_SIZE = 16 * 320 * 1024  # 5.2MB
-MAX_RETRIES = 5
+TIMEOUT = ClientTimeout(connect=10, total=43200)  # 12 hours
 
 
 async def async_get_backup_agents(
@@ -92,18 +77,18 @@ def handle_backup_errors[_R, **P](
     ) -> _R:
         try:
             return await func(self, *args, **kwargs)
-        except APIError as err:
-            if err.response_status_code == 403:
-                self._entry.async_start_reauth(self._hass)
+        except AuthenticationError as err:
+            self._entry.async_start_reauth(self._hass)
+            raise BackupAgentError("Authentication error") from err
+        except OneDriveException as err:
             _LOGGER.error(
-                "Error during backup in %s: Status %s, message %s",
+                "Error during backup in %s:, message %s",
                 func.__name__,
-                err.response_status_code,
-                err.message,
+                err,
             )
             _LOGGER.debug("Full error: %s", err, exc_info=True)
             raise BackupAgentError("Backup operation failed") from err
-        except TimeoutException as err:
+        except TimeoutError as err:
             _LOGGER.error(
                 "Error during backup in %s: Timeout",
                 func.__name__,
@@ -123,7 +108,8 @@ class OneDriveBackupAgent(BackupAgent):
         super().__init__()
         self._hass = hass
         self._entry = entry
-        self._items = entry.runtime_data.items
+        self._client = entry.runtime_data.client
+        self._token_provider = entry.runtime_data.token_provider
         self._folder_id = entry.runtime_data.backup_folder_id
         self.name = entry.title
         assert entry.unique_id
@@ -134,24 +120,12 @@ class OneDriveBackupAgent(BackupAgent):
         self, backup_id: str, **kwargs: Any
     ) -> AsyncIterator[bytes]:
         """Download a backup file."""
-        # this forces the query to return a raw httpx response, but breaks typing
-        backup = await self._find_item_by_backup_id(backup_id)
-        if backup is None or backup.id is None:
+        item = await self._find_item_by_backup_id(backup_id)
+        if item is None:
             raise BackupAgentError("Backup not found")
 
-        request_config = (
-            ContentRequestBuilder.ContentRequestBuilderGetRequestConfiguration(
-                options=[ResponseHandlerOption(NativeResponseHandler())],
-            )
-        )
-        response = cast(
-            Response,
-            await self._items.by_drive_item_id(backup.id).content.get(
-                request_configuration=request_config
-            ),
-        )
-
-        return response.aiter_bytes(chunk_size=1024)
+        stream = await self._client.download_drive_item(item.id, timeout=TIMEOUT)
+        return stream.iter_chunked(1024)
 
     @handle_backup_errors
     async def async_upload_backup(
@@ -163,27 +137,20 @@ class OneDriveBackupAgent(BackupAgent):
     ) -> None:
         """Upload a backup."""
 
-        # upload file in chunks to support large files
-        upload_session_request_body = CreateUploadSessionPostRequestBody(
-            item=DriveItemUploadableProperties(
-                additional_data={
-                    "@microsoft.graph.conflictBehavior": "fail",
-                },
-            )
+        file = FileInfo(
+            suggested_filename(backup),
+            backup.size,
+            self._folder_id,
+            await open_stream(),
         )
-        file_item = self._get_backup_file_item(suggested_filename(backup))
-        upload_session = await file_item.create_upload_session.post(
-            upload_session_request_body
-        )
-
-        if upload_session is None or upload_session.upload_url is None:
-            raise BackupAgentError(
-                translation_domain=DOMAIN, translation_key="backup_no_upload_session"
+        try:
+            item = await LargeFileUploadClient.upload(
+                self._token_provider, file, session=async_get_clientsession(self._hass)
             )
-
-        await self._upload_file(
-            upload_session.upload_url, await open_stream(), backup.size
-        )
+        except HashMismatchError as err:
+            raise BackupAgentError(
+                "Hash validation failed, backup file might be corrupt"
+            ) from err
 
         # store metadata in description
         backup_dict = backup.as_dict()
@@ -191,7 +158,10 @@ class OneDriveBackupAgent(BackupAgent):
         description = json.dumps(backup_dict)
         _LOGGER.debug("Creating metadata: %s", description)
 
-        await file_item.patch(DriveItem(description=description))
+        await self._client.update_drive_item(
+            path_or_id=item.id,
+            data=ItemUpdate(description=description),
+        )
 
     @handle_backup_errors
     async def async_delete_backup(
@@ -200,35 +170,31 @@ class OneDriveBackupAgent(BackupAgent):
         **kwargs: Any,
     ) -> None:
         """Delete a backup file."""
-        backup = await self._find_item_by_backup_id(backup_id)
-        if backup is None or backup.id is None:
+        item = await self._find_item_by_backup_id(backup_id)
+        if item is None:
             return
-        await self._items.by_drive_item_id(backup.id).delete()
+        await self._client.delete_drive_item(item.id)
 
     @handle_backup_errors
     async def async_list_backups(self, **kwargs: Any) -> list[AgentBackup]:
         """List backups."""
-        backups: list[AgentBackup] = []
-        items = await self._items.by_drive_item_id(f"{self._folder_id}").children.get()
-        if items and (values := items.value):
-            for item in values:
-                if (description := item.description) is None:
-                    continue
-                if "homeassistant_version" in description:
-                    backups.append(self._backup_from_description(description))
-        return backups
+        return [
+            self._backup_from_description(item.description)
+            for item in await self._client.list_drive_items(self._folder_id)
+            if item.description and "homeassistant_version" in item.description
+        ]
 
     @handle_backup_errors
     async def async_get_backup(
         self, backup_id: str, **kwargs: Any
     ) -> AgentBackup | None:
         """Return a backup."""
-        backup = await self._find_item_by_backup_id(backup_id)
-        if backup is None:
-            return None
-
-        assert backup.description  # already checked in _find_item_by_backup_id
-        return self._backup_from_description(backup.description)
+        item = await self._find_item_by_backup_id(backup_id)
+        return (
+            self._backup_from_description(item.description)
+            if item and item.description
+            else None
+        )
 
     def _backup_from_description(self, description: str) -> AgentBackup:
         """Create a backup object from a description."""
@@ -237,91 +203,13 @@ class OneDriveBackupAgent(BackupAgent):
         )  # OneDrive encodes the description on save automatically
         return AgentBackup.from_dict(json.loads(description))
 
-    async def _find_item_by_backup_id(self, backup_id: str) -> DriveItem | None:
-        """Find a backup item by its backup ID."""
-
-        items = await self._items.by_drive_item_id(f"{self._folder_id}").children.get()
-        if items and (values := items.value):
-            for item in values:
-                if (description := item.description) is None:
-                    continue
-                if backup_id in description:
-                    return item
-        return None
-
-    def _get_backup_file_item(self, backup_id: str) -> DriveItemItemRequestBuilder:
-        return self._items.by_drive_item_id(f"{self._folder_id}:/{backup_id}:")
-
-    async def _upload_file(
-        self, upload_url: str, stream: AsyncIterator[bytes], total_size: int
-    ) -> None:
-        """Use custom large file upload; SDK does not support stream."""
-
-        adapter = GraphRequestAdapter(
-            auth_provider=AnonymousAuthenticationProvider(),
-            client=get_async_client(self._hass),
+    async def _find_item_by_backup_id(self, backup_id: str) -> File | Folder | None:
+        """Find an item by backup ID."""
+        return next(
+            (
+                item
+                for item in await self._client.list_drive_items(self._folder_id)
+                if item.description and backup_id in item.description
+            ),
+            None,
         )
-
-        async def async_upload(
-            start: int, end: int, chunk_data: bytes
-        ) -> LargeFileUploadSession:
-            info = RequestInformation()
-            info.url = upload_url
-            info.http_method = Method.PUT
-            info.headers = HeadersCollection()
-            info.headers.try_add("Content-Range", f"bytes {start}-{end}/{total_size}")
-            info.headers.try_add("Content-Length", str(len(chunk_data)))
-            info.headers.try_add("Content-Type", "application/octet-stream")
-            _LOGGER.debug(info.headers.get_all())
-            info.set_stream_content(chunk_data)
-            result = await adapter.send_async(info, LargeFileUploadSession, {})
-            _LOGGER.debug("Next expected range: %s", result.next_expected_ranges)
-            return result
-
-        start = 0
-        buffer: list[bytes] = []
-        buffer_size = 0
-        retries = 0
-
-        async for chunk in stream:
-            buffer.append(chunk)
-            buffer_size += len(chunk)
-            if buffer_size >= UPLOAD_CHUNK_SIZE:
-                chunk_data = b"".join(buffer)
-                uploaded_chunks = 0
-                while (
-                    buffer_size > UPLOAD_CHUNK_SIZE
-                ):  # Loop in case the buffer is >= UPLOAD_CHUNK_SIZE * 2
-                    slice_start = uploaded_chunks * UPLOAD_CHUNK_SIZE
-                    try:
-                        await async_upload(
-                            start,
-                            start + UPLOAD_CHUNK_SIZE - 1,
-                            chunk_data[slice_start : slice_start + UPLOAD_CHUNK_SIZE],
-                        )
-                    except APIError as err:
-                        if (
-                            err.response_status_code and err.response_status_code < 500
-                        ):  # no retry on 4xx errors
-                            raise
-                        if retries < MAX_RETRIES:
-                            await asyncio.sleep(2**retries)
-                            retries += 1
-                            continue
-                        raise
-                    except TimeoutException:
-                        if retries < MAX_RETRIES:
-                            retries += 1
-                            continue
-                        raise
-                    retries = 0
-                    start += UPLOAD_CHUNK_SIZE
-                    uploaded_chunks += 1
-                    buffer_size -= UPLOAD_CHUNK_SIZE
-                buffer = [chunk_data[UPLOAD_CHUNK_SIZE * uploaded_chunks :]]
-
-        # upload the remaining bytes
-        if buffer:
-            _LOGGER.debug("Last chunk")
-            chunk_data = b"".join(buffer)
-            await async_upload(start, start + len(chunk_data) - 1, chunk_data)
diff --git a/homeassistant/components/onedrive/config_flow.py b/homeassistant/components/onedrive/config_flow.py
index 09c0d1b44ccc1503840750bdcbec9f1d7d8d57c9..cbdf59648b922d18daa7edb45cd87a37c2748ed2 100644
--- a/homeassistant/components/onedrive/config_flow.py
+++ b/homeassistant/components/onedrive/config_flow.py
@@ -4,16 +4,13 @@ from collections.abc import Mapping
 import logging
 from typing import Any, cast
 
-from kiota_abstractions.api_error import APIError
-from kiota_abstractions.authentication import BaseBearerTokenAuthenticationProvider
-from kiota_abstractions.method import Method
-from kiota_abstractions.request_information import RequestInformation
-from msgraph import GraphRequestAdapter, GraphServiceClient
+from onedrive_personal_sdk.clients.client import OneDriveClient
+from onedrive_personal_sdk.exceptions import OneDriveException
 
 from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult
 from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN
+from homeassistant.helpers.aiohttp_client import async_get_clientsession
 from homeassistant.helpers.config_entry_oauth2_flow import AbstractOAuth2FlowHandler
-from homeassistant.helpers.httpx_client import get_async_client
 
 from .api import OneDriveConfigFlowAccessTokenProvider
 from .const import DOMAIN, OAUTH_SCOPES
@@ -39,48 +36,24 @@ class OneDriveConfigFlow(AbstractOAuth2FlowHandler, domain=DOMAIN):
         data: dict[str, Any],
     ) -> ConfigFlowResult:
         """Handle the initial step."""
-        auth_provider = BaseBearerTokenAuthenticationProvider(
-            access_token_provider=OneDriveConfigFlowAccessTokenProvider(
-                cast(str, data[CONF_TOKEN][CONF_ACCESS_TOKEN])
-            )
-        )
-        adapter = GraphRequestAdapter(
-            auth_provider=auth_provider,
-            client=get_async_client(self.hass),
+        token_provider = OneDriveConfigFlowAccessTokenProvider(
+            cast(str, data[CONF_TOKEN][CONF_ACCESS_TOKEN])
         )
 
-        graph_client = GraphServiceClient(
-            request_adapter=adapter,
-            scopes=OAUTH_SCOPES,
-        )
-
-        # need to get adapter from client, as client changes it
-        request_adapter = cast(GraphRequestAdapter, graph_client.request_adapter)
-
-        request_info = RequestInformation(
-            method=Method.GET,
-            url_template="{+baseurl}/me/drive/special/approot",
-            path_parameters={},
+        graph_client = OneDriveClient(
+            token_provider, async_get_clientsession(self.hass)
         )
-        parent_span = request_adapter.start_tracing_span(request_info, "get_approot")
 
-        # get the OneDrive id
-        # use low level methods, to avoid files.read permissions
-        # which would be required by drives.me.get()
         try:
-            response = await request_adapter.get_http_response_message(
-                request_info=request_info, parent_span=parent_span
-            )
-        except APIError:
+            approot = await graph_client.get_approot()
+        except OneDriveException:
             self.logger.exception("Failed to connect to OneDrive")
             return self.async_abort(reason="connection_error")
         except Exception:
             self.logger.exception("Unknown error")
             return self.async_abort(reason="unknown")
 
-        drive: dict = response.json()
-
-        await self.async_set_unique_id(drive["parentReference"]["driveId"])
+        await self.async_set_unique_id(approot.parent_reference.drive_id)
 
         if self.source == SOURCE_REAUTH:
             reauth_entry = self._get_reauth_entry()
@@ -94,10 +67,11 @@ class OneDriveConfigFlow(AbstractOAuth2FlowHandler, domain=DOMAIN):
 
         self._abort_if_unique_id_configured()
 
-        user = drive.get("createdBy", {}).get("user", {}).get("displayName")
-
-        title = f"{user}'s OneDrive" if user else "OneDrive"
-
+        title = (
+            f"{approot.created_by.user.display_name}'s OneDrive"
+            if approot.created_by.user and approot.created_by.user.display_name
+            else "OneDrive"
+        )
         return self.async_create_entry(title=title, data=data)
 
     async def async_step_reauth(
diff --git a/homeassistant/components/onedrive/manifest.json b/homeassistant/components/onedrive/manifest.json
index 056e31864a48739493e269fe7e648206945ae5a7..767426058c1752391d03716be2e98921fa2a2220 100644
--- a/homeassistant/components/onedrive/manifest.json
+++ b/homeassistant/components/onedrive/manifest.json
@@ -7,7 +7,7 @@
   "documentation": "https://www.home-assistant.io/integrations/onedrive",
   "integration_type": "service",
   "iot_class": "cloud_polling",
-  "loggers": ["msgraph", "msgraph-core", "kiota"],
+  "loggers": ["onedrive_personal_sdk"],
   "quality_scale": "bronze",
-  "requirements": ["msgraph-sdk==1.16.0"]
+  "requirements": ["onedrive-personal-sdk==0.0.1"]
 }
diff --git a/homeassistant/components/onedrive/strings.json b/homeassistant/components/onedrive/strings.json
index 9cbdb2bdeae13d0d819d0f5a73e55b901ca36e15..7686e83e2a56288fd1fda5b17165ac64285a6340 100644
--- a/homeassistant/components/onedrive/strings.json
+++ b/homeassistant/components/onedrive/strings.json
@@ -23,31 +23,18 @@
       "connection_error": "Failed to connect to OneDrive.",
       "wrong_drive": "New account does not contain previously configured OneDrive.",
       "unknown": "[%key:common::config_flow::error::unknown%]",
-      "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
-      "failed_to_create_folder": "Failed to create backup folder"
+      "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
     },
     "create_entry": {
       "default": "[%key:common::config_flow::create_entry::authenticated%]"
     }
   },
   "exceptions": {
-    "backup_not_found": {
-      "message": "Backup not found"
-    },
-    "backup_no_content": {
-      "message": "Backup has no content"
-    },
-    "backup_no_upload_session": {
-      "message": "Failed to start backup upload"
-    },
     "authentication_failed": {
       "message": "Authentication failed"
     },
     "failed_to_get_folder": {
       "message": "Failed to get {folder} folder"
-    },
-    "failed_to_create_folder": {
-      "message": "Failed to create {folder} folder"
     }
   }
 }
diff --git a/requirements_all.txt b/requirements_all.txt
index f0ad42f0ebad7149f32f910407300aa183e51364..18ebb5d4a090cb5e445ea1c06088fbd502c22fac 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -1434,9 +1434,6 @@ motioneye-client==0.3.14
 # homeassistant.components.bang_olufsen
 mozart-api==4.1.1.116.4
 
-# homeassistant.components.onedrive
-msgraph-sdk==1.16.0
-
 # homeassistant.components.mullvad
 mullvad-api==1.0.0
 
@@ -1558,6 +1555,9 @@ omnilogic==0.4.5
 # homeassistant.components.ondilo_ico
 ondilo==0.5.0
 
+# homeassistant.components.onedrive
+onedrive-personal-sdk==0.0.1
+
 # homeassistant.components.onvif
 onvif-zeep-async==3.2.5
 
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index a1fee30ffd395acba4a4cba915ef7805507c15a6..575e6f6b4045a36596572bad2844c7d21185fb32 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -1206,9 +1206,6 @@ motioneye-client==0.3.14
 # homeassistant.components.bang_olufsen
 mozart-api==4.1.1.116.4
 
-# homeassistant.components.onedrive
-msgraph-sdk==1.16.0
-
 # homeassistant.components.mullvad
 mullvad-api==1.0.0
 
@@ -1306,6 +1303,9 @@ omnilogic==0.4.5
 # homeassistant.components.ondilo_ico
 ondilo==0.5.0
 
+# homeassistant.components.onedrive
+onedrive-personal-sdk==0.0.1
+
 # homeassistant.components.onvif
 onvif-zeep-async==3.2.5
 
diff --git a/tests/components/onedrive/conftest.py b/tests/components/onedrive/conftest.py
index 205f5837ee7670dffc5602c25b8e259cd079a522..e76ce1d01c86c01c0fcad6a274b326782dc39457 100644
--- a/tests/components/onedrive/conftest.py
+++ b/tests/components/onedrive/conftest.py
@@ -1,18 +1,9 @@
 """Fixtures for OneDrive tests."""
 
 from collections.abc import AsyncIterator, Generator
-from html import escape
-from json import dumps
 import time
 from unittest.mock import AsyncMock, MagicMock, patch
 
-from httpx import Response
-from msgraph.generated.models.drive_item import DriveItem
-from msgraph.generated.models.drive_item_collection_response import (
-    DriveItemCollectionResponse,
-)
-from msgraph.generated.models.upload_session import UploadSession
-from msgraph_core.models import LargeFileUploadSession
 import pytest
 
 from homeassistant.components.application_credentials import (
@@ -23,7 +14,13 @@ from homeassistant.components.onedrive.const import DOMAIN, OAUTH_SCOPES
 from homeassistant.core import HomeAssistant
 from homeassistant.setup import async_setup_component
 
-from .const import BACKUP_METADATA, CLIENT_ID, CLIENT_SECRET
+from .const import (
+    CLIENT_ID,
+    CLIENT_SECRET,
+    MOCK_APPROOT,
+    MOCK_BACKUP_FILE,
+    MOCK_BACKUP_FOLDER,
+)
 
 from tests.common import MockConfigEntry
 
@@ -70,96 +67,41 @@ def mock_config_entry(expires_at: int, scopes: list[str]) -> MockConfigEntry:
     )
 
 
-@pytest.fixture
-def mock_adapter() -> Generator[MagicMock]:
-    """Return a mocked GraphAdapter."""
-    with (
-        patch(
-            "homeassistant.components.onedrive.config_flow.GraphRequestAdapter",
-            autospec=True,
-        ) as mock_adapter,
-        patch(
-            "homeassistant.components.onedrive.backup.GraphRequestAdapter",
-            new=mock_adapter,
-        ),
-    ):
-        adapter = mock_adapter.return_value
-        adapter.get_http_response_message.return_value = Response(
-            status_code=200,
-            json={
-                "parentReference": {"driveId": "mock_drive_id"},
-                "createdBy": {"user": {"displayName": "John Doe"}},
-            },
-        )
-        yield adapter
-        adapter.send_async.return_value = LargeFileUploadSession(
-            next_expected_ranges=["2-"]
-        )
-
-
 @pytest.fixture(autouse=True)
-def mock_graph_client(mock_adapter: MagicMock) -> Generator[MagicMock]:
+def mock_onedrive_client() -> Generator[MagicMock]:
     """Return a mocked GraphServiceClient."""
     with (
         patch(
-            "homeassistant.components.onedrive.config_flow.GraphServiceClient",
+            "homeassistant.components.onedrive.config_flow.OneDriveClient",
             autospec=True,
-        ) as graph_client,
+        ) as onedrive_client,
         patch(
-            "homeassistant.components.onedrive.GraphServiceClient",
-            new=graph_client,
+            "homeassistant.components.onedrive.OneDriveClient",
+            new=onedrive_client,
         ),
     ):
-        client = graph_client.return_value
-
-        client.request_adapter = mock_adapter
-
-        drives = client.drives.by_drive_id.return_value
-        drives.special.by_drive_item_id.return_value.get = AsyncMock(
-            return_value=DriveItem(id="approot")
-        )
-
-        drive_items = drives.items.by_drive_item_id.return_value
-        drive_items.get = AsyncMock(return_value=DriveItem(id="folder_id"))
-        drive_items.children.post = AsyncMock(return_value=DriveItem(id="folder_id"))
-        drive_items.children.get = AsyncMock(
-            return_value=DriveItemCollectionResponse(
-                value=[
-                    DriveItem(
-                        id=BACKUP_METADATA["backup_id"],
-                        description=escape(dumps(BACKUP_METADATA)),
-                    ),
-                    DriveItem(),
-                ]
-            )
-        )
-        drive_items.delete = AsyncMock(return_value=None)
-        drive_items.create_upload_session.post = AsyncMock(
-            return_value=UploadSession(upload_url="https://test.tld")
-        )
-        drive_items.patch = AsyncMock(return_value=None)
-
-        async def generate_bytes() -> AsyncIterator[bytes]:
-            """Asynchronous generator that yields bytes."""
-            yield b"backup data"
-
-        drive_items.content.get = AsyncMock(
-            return_value=Response(status_code=200, content=generate_bytes())
-        )
+        client = onedrive_client.return_value
+        client.get_approot.return_value = MOCK_APPROOT
+        client.create_folder.return_value = MOCK_BACKUP_FOLDER
+        client.list_drive_items.return_value = [MOCK_BACKUP_FILE]
+        client.get_drive_item.return_value = MOCK_BACKUP_FILE
 
-        yield client
+        class MockStreamReader:
+            async def iter_chunked(self, chunk_size: int) -> AsyncIterator[bytes]:
+                yield b"backup data"
 
+        client.download_drive_item.return_value = MockStreamReader()
 
-@pytest.fixture
-def mock_drive_items(mock_graph_client: MagicMock) -> MagicMock:
-    """Return a mocked DriveItems."""
-    return mock_graph_client.drives.by_drive_id.return_value.items.by_drive_item_id.return_value
+        yield client
 
 
 @pytest.fixture
-def mock_get_special_folder(mock_graph_client: MagicMock) -> MagicMock:
-    """Mock the get special folder method."""
-    return mock_graph_client.drives.by_drive_id.return_value.special.by_drive_item_id.return_value.get
+def mock_large_file_upload_client() -> Generator[AsyncMock]:
+    """Return a mocked LargeFileUploadClient upload."""
+    with patch(
+        "homeassistant.components.onedrive.backup.LargeFileUploadClient.upload"
+    ) as mock_upload:
+        yield mock_upload
 
 
 @pytest.fixture
@@ -179,10 +121,3 @@ def mock_instance_id() -> Generator[AsyncMock]:
         return_value="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0",
     ):
         yield
-
-
-@pytest.fixture(autouse=True)
-def mock_asyncio_sleep() -> Generator[AsyncMock]:
-    """Mock asyncio.sleep."""
-    with patch("homeassistant.components.onedrive.backup.asyncio.sleep", AsyncMock()):
-        yield
diff --git a/tests/components/onedrive/const.py b/tests/components/onedrive/const.py
index c187feef30a40ef21fedbbdac5f9b73a7aea4cce..ee3a5ce3dc420e1ea8847f36fddef4f960dcb37a 100644
--- a/tests/components/onedrive/const.py
+++ b/tests/components/onedrive/const.py
@@ -1,5 +1,18 @@
 """Consts for OneDrive tests."""
 
+from html import escape
+from json import dumps
+
+from onedrive_personal_sdk.models.items import (
+    AppRoot,
+    Contributor,
+    File,
+    Folder,
+    Hashes,
+    ItemParentReference,
+    User,
+)
+
 CLIENT_ID = "1234"
 CLIENT_SECRET = "5678"
 
@@ -17,3 +30,48 @@ BACKUP_METADATA = {
     "protected": False,
     "size": 34519040,
 }
+
+CONTRIBUTOR = Contributor(
+    user=User(
+        display_name="John Doe",
+        id="id",
+        email="john@doe.com",
+    )
+)
+
+MOCK_APPROOT = AppRoot(
+    id="id",
+    child_count=0,
+    size=0,
+    name="name",
+    parent_reference=ItemParentReference(
+        drive_id="mock_drive_id", id="id", path="path"
+    ),
+    created_by=CONTRIBUTOR,
+)
+
+MOCK_BACKUP_FOLDER = Folder(
+    id="id",
+    name="name",
+    size=0,
+    child_count=0,
+    parent_reference=ItemParentReference(
+        drive_id="mock_drive_id", id="id", path="path"
+    ),
+    created_by=CONTRIBUTOR,
+)
+
+MOCK_BACKUP_FILE = File(
+    id="id",
+    name="23e64aec.tar",
+    size=34519040,
+    parent_reference=ItemParentReference(
+        drive_id="mock_drive_id", id="id", path="path"
+    ),
+    hashes=Hashes(
+        quick_xor_hash="hash",
+    ),
+    mime_type="application/x-tar",
+    description=escape(dumps(BACKUP_METADATA)),
+    created_by=CONTRIBUTOR,
+)
diff --git a/tests/components/onedrive/test_backup.py b/tests/components/onedrive/test_backup.py
index 0114d924e1a876a7804c92a8b50742ba42c3464d..3f8c29efa7e48cc45a7d70c254ad58cb4b112cc1 100644
--- a/tests/components/onedrive/test_backup.py
+++ b/tests/components/onedrive/test_backup.py
@@ -3,15 +3,14 @@
 from __future__ import annotations
 
 from collections.abc import AsyncGenerator
-from html import escape
 from io import StringIO
-from json import dumps
 from unittest.mock import Mock, patch
 
-from httpx import TimeoutException
-from kiota_abstractions.api_error import APIError
-from msgraph.generated.models.drive_item import DriveItem
-from msgraph_core.models import LargeFileUploadSession
+from onedrive_personal_sdk.exceptions import (
+    AuthenticationError,
+    HashMismatchError,
+    OneDriveException,
+)
 import pytest
 
 from homeassistant.components.backup import DOMAIN as BACKUP_DOMAIN, AgentBackup
@@ -102,14 +101,10 @@ async def test_agents_list_backups(
 async def test_agents_get_backup(
     hass: HomeAssistant,
     hass_ws_client: WebSocketGenerator,
-    mock_drive_items: MagicMock,
     mock_config_entry: MockConfigEntry,
 ) -> None:
     """Test agent get backup."""
 
-    mock_drive_items.get = AsyncMock(
-        return_value=DriveItem(description=escape(dumps(BACKUP_METADATA)))
-    )
     backup_id = BACKUP_METADATA["backup_id"]
     client = await hass_ws_client(hass)
     await client.send_json_auto_id({"type": "backup/details", "backup_id": backup_id})
@@ -140,7 +135,7 @@ async def test_agents_get_backup(
 async def test_agents_delete(
     hass: HomeAssistant,
     hass_ws_client: WebSocketGenerator,
-    mock_drive_items: MagicMock,
+    mock_onedrive_client: MagicMock,
 ) -> None:
     """Test agent delete backup."""
     client = await hass_ws_client(hass)
@@ -155,37 +150,15 @@ async def test_agents_delete(
 
     assert response["success"]
     assert response["result"] == {"agent_errors": {}}
-    mock_drive_items.delete.assert_called_once()
-
-
-async def test_agents_delete_not_found_does_not_throw(
-    hass: HomeAssistant,
-    hass_ws_client: WebSocketGenerator,
-    mock_drive_items: MagicMock,
-) -> None:
-    """Test agent delete backup."""
-    mock_drive_items.children.get = AsyncMock(return_value=[])
-    client = await hass_ws_client(hass)
-
-    await client.send_json_auto_id(
-        {
-            "type": "backup/delete",
-            "backup_id": BACKUP_METADATA["backup_id"],
-        }
-    )
-    response = await client.receive_json()
-
-    assert response["success"]
-    assert response["result"] == {"agent_errors": {}}
-    assert mock_drive_items.delete.call_count == 0
+    mock_onedrive_client.delete_drive_item.assert_called_once()
 
 
 async def test_agents_upload(
     hass_client: ClientSessionGenerator,
     caplog: pytest.LogCaptureFixture,
-    mock_drive_items: MagicMock,
+    mock_onedrive_client: MagicMock,
+    mock_large_file_upload_client: AsyncMock,
     mock_config_entry: MockConfigEntry,
-    mock_adapter: MagicMock,
 ) -> None:
     """Test agent upload backup."""
     client = await hass_client()
@@ -200,7 +173,6 @@ async def test_agents_upload(
             return_value=test_backup,
         ),
         patch("pathlib.Path.open") as mocked_open,
-        patch("homeassistant.components.onedrive.backup.UPLOAD_CHUNK_SIZE", 3),
     ):
         mocked_open.return_value.read = Mock(side_effect=[b"test", b""])
         fetch_backup.return_value = test_backup
@@ -211,77 +183,22 @@ async def test_agents_upload(
 
     assert resp.status == 201
     assert f"Uploading backup {test_backup.backup_id}" in caplog.text
-    mock_drive_items.create_upload_session.post.assert_called_once()
-    mock_drive_items.patch.assert_called_once()
-    assert mock_adapter.send_async.call_count == 2
-    assert mock_adapter.method_calls[0].args[0].content == b"tes"
-    assert mock_adapter.method_calls[0].args[0].headers.get("Content-Range") == {
-        "bytes 0-2/34519040"
-    }
-    assert mock_adapter.method_calls[1].args[0].content == b"t"
-    assert mock_adapter.method_calls[1].args[0].headers.get("Content-Range") == {
-        "bytes 3-3/34519040"
-    }
-
-
-async def test_broken_upload_session(
-    hass_client: ClientSessionGenerator,
-    caplog: pytest.LogCaptureFixture,
-    mock_drive_items: MagicMock,
-    mock_config_entry: MockConfigEntry,
-) -> None:
-    """Test broken upload session."""
-    client = await hass_client()
-    test_backup = AgentBackup.from_dict(BACKUP_METADATA)
-
-    mock_drive_items.create_upload_session.post = AsyncMock(return_value=None)
-
-    with (
-        patch(
-            "homeassistant.components.backup.manager.BackupManager.async_get_backup",
-        ) as fetch_backup,
-        patch(
-            "homeassistant.components.backup.manager.read_backup",
-            return_value=test_backup,
-        ),
-        patch("pathlib.Path.open") as mocked_open,
-    ):
-        mocked_open.return_value.read = Mock(side_effect=[b"test", b""])
-        fetch_backup.return_value = test_backup
-        resp = await client.post(
-            f"/api/backup/upload?agent_id={DOMAIN}.{mock_config_entry.unique_id}",
-            data={"file": StringIO("test")},
-        )
+    mock_large_file_upload_client.assert_called_once()
+    mock_onedrive_client.update_drive_item.assert_called_once()
 
-    assert resp.status == 201
-    assert "Failed to start backup upload" in caplog.text
 
-
-@pytest.mark.parametrize(
-    "side_effect",
-    [
-        APIError(response_status_code=500),
-        TimeoutException("Timeout"),
-    ],
-)
-async def test_agents_upload_errors_retried(
+async def test_agents_upload_corrupt_upload(
     hass_client: ClientSessionGenerator,
     caplog: pytest.LogCaptureFixture,
-    mock_drive_items: MagicMock,
+    mock_onedrive_client: MagicMock,
+    mock_large_file_upload_client: AsyncMock,
     mock_config_entry: MockConfigEntry,
-    mock_adapter: MagicMock,
-    side_effect: Exception,
 ) -> None:
-    """Test agent upload backup."""
+    """Test hash validation fails."""
+    mock_large_file_upload_client.side_effect = HashMismatchError("test")
     client = await hass_client()
     test_backup = AgentBackup.from_dict(BACKUP_METADATA)
 
-    mock_adapter.send_async.side_effect = [
-        side_effect,
-        LargeFileUploadSession(next_expected_ranges=["2-"]),
-        LargeFileUploadSession(next_expected_ranges=["2-"]),
-    ]
-
     with (
         patch(
             "homeassistant.components.backup.manager.BackupManager.async_get_backup",
@@ -291,7 +208,6 @@ async def test_agents_upload_errors_retried(
             return_value=test_backup,
         ),
         patch("pathlib.Path.open") as mocked_open,
-        patch("homeassistant.components.onedrive.backup.UPLOAD_CHUNK_SIZE", 3),
     ):
         mocked_open.return_value.read = Mock(side_effect=[b"test", b""])
         fetch_backup.return_value = test_backup
@@ -301,105 +217,18 @@ async def test_agents_upload_errors_retried(
         )
 
     assert resp.status == 201
-    assert mock_adapter.send_async.call_count == 3
     assert f"Uploading backup {test_backup.backup_id}" in caplog.text
-    mock_drive_items.patch.assert_called_once()
-
-
-async def test_agents_upload_4xx_errors_not_retried(
-    hass_client: ClientSessionGenerator,
-    caplog: pytest.LogCaptureFixture,
-    mock_drive_items: MagicMock,
-    mock_config_entry: MockConfigEntry,
-    mock_adapter: MagicMock,
-) -> None:
-    """Test agent upload backup."""
-    client = await hass_client()
-    test_backup = AgentBackup.from_dict(BACKUP_METADATA)
-
-    mock_adapter.send_async.side_effect = APIError(response_status_code=404)
-
-    with (
-        patch(
-            "homeassistant.components.backup.manager.BackupManager.async_get_backup",
-        ) as fetch_backup,
-        patch(
-            "homeassistant.components.backup.manager.read_backup",
-            return_value=test_backup,
-        ),
-        patch("pathlib.Path.open") as mocked_open,
-        patch("homeassistant.components.onedrive.backup.UPLOAD_CHUNK_SIZE", 3),
-    ):
-        mocked_open.return_value.read = Mock(side_effect=[b"test", b""])
-        fetch_backup.return_value = test_backup
-        resp = await client.post(
-            f"/api/backup/upload?agent_id={DOMAIN}.{mock_config_entry.unique_id}",
-            data={"file": StringIO("test")},
-        )
-
-    assert resp.status == 201
-    assert mock_adapter.send_async.call_count == 1
-    assert f"Uploading backup {test_backup.backup_id}" in caplog.text
-    assert mock_drive_items.patch.call_count == 0
-    assert "Backup operation failed" in caplog.text
-
-
-@pytest.mark.parametrize(
-    ("side_effect", "error"),
-    [
-        (APIError(response_status_code=500), "Backup operation failed"),
-        (TimeoutException("Timeout"), "Backup operation timed out"),
-    ],
-)
-async def test_agents_upload_fails_after_max_retries(
-    hass_client: ClientSessionGenerator,
-    caplog: pytest.LogCaptureFixture,
-    mock_drive_items: MagicMock,
-    mock_config_entry: MockConfigEntry,
-    mock_adapter: MagicMock,
-    side_effect: Exception,
-    error: str,
-) -> None:
-    """Test agent upload backup."""
-    client = await hass_client()
-    test_backup = AgentBackup.from_dict(BACKUP_METADATA)
-
-    mock_adapter.send_async.side_effect = side_effect
-
-    with (
-        patch(
-            "homeassistant.components.backup.manager.BackupManager.async_get_backup",
-        ) as fetch_backup,
-        patch(
-            "homeassistant.components.backup.manager.read_backup",
-            return_value=test_backup,
-        ),
-        patch("pathlib.Path.open") as mocked_open,
-        patch("homeassistant.components.onedrive.backup.UPLOAD_CHUNK_SIZE", 3),
-    ):
-        mocked_open.return_value.read = Mock(side_effect=[b"test", b""])
-        fetch_backup.return_value = test_backup
-        resp = await client.post(
-            f"/api/backup/upload?agent_id={DOMAIN}.{mock_config_entry.unique_id}",
-            data={"file": StringIO("test")},
-        )
-
-    assert resp.status == 201
-    assert mock_adapter.send_async.call_count == 6
-    assert f"Uploading backup {test_backup.backup_id}" in caplog.text
-    assert mock_drive_items.patch.call_count == 0
-    assert error in caplog.text
+    mock_large_file_upload_client.assert_called_once()
+    assert mock_onedrive_client.update_drive_item.call_count == 0
+    assert "Hash validation failed, backup file might be corrupt" in caplog.text
 
 
 async def test_agents_download(
     hass_client: ClientSessionGenerator,
-    mock_drive_items: MagicMock,
+    mock_onedrive_client: MagicMock,
     mock_config_entry: MockConfigEntry,
 ) -> None:
     """Test agent download backup."""
-    mock_drive_items.get = AsyncMock(
-        return_value=DriveItem(description=escape(dumps(BACKUP_METADATA)))
-    )
     client = await hass_client()
     backup_id = BACKUP_METADATA["backup_id"]
 
@@ -408,29 +237,30 @@ async def test_agents_download(
     )
     assert resp.status == 200
     assert await resp.content.read() == b"backup data"
-    mock_drive_items.content.get.assert_called_once()
 
 
 @pytest.mark.parametrize(
     ("side_effect", "error"),
     [
         (
-            APIError(response_status_code=500),
+            OneDriveException(),
             "Backup operation failed",
         ),
-        (TimeoutException("Timeout"), "Backup operation timed out"),
+        (TimeoutError(), "Backup operation timed out"),
     ],
 )
 async def test_delete_error(
     hass: HomeAssistant,
     hass_ws_client: WebSocketGenerator,
-    mock_drive_items: MagicMock,
+    mock_onedrive_client: MagicMock,
     mock_config_entry: MockConfigEntry,
     side_effect: Exception,
     error: str,
 ) -> None:
     """Test error during delete."""
-    mock_drive_items.delete = AsyncMock(side_effect=side_effect)
+    mock_onedrive_client.delete_drive_item.side_effect = AsyncMock(
+        side_effect=side_effect
+    )
 
     client = await hass_ws_client(hass)
 
@@ -448,14 +278,35 @@ async def test_delete_error(
     }
 
 
+async def test_agents_delete_not_found_does_not_throw(
+    hass: HomeAssistant,
+    hass_ws_client: WebSocketGenerator,
+    mock_onedrive_client: MagicMock,
+) -> None:
+    """Test agent delete backup."""
+    mock_onedrive_client.list_drive_items.return_value = []
+    client = await hass_ws_client(hass)
+
+    await client.send_json_auto_id(
+        {
+            "type": "backup/delete",
+            "backup_id": BACKUP_METADATA["backup_id"],
+        }
+    )
+    response = await client.receive_json()
+
+    assert response["success"]
+    assert response["result"] == {"agent_errors": {}}
+
+
 async def test_agents_backup_not_found(
     hass: HomeAssistant,
     hass_ws_client: WebSocketGenerator,
-    mock_drive_items: MagicMock,
+    mock_onedrive_client: MagicMock,
 ) -> None:
     """Test backup not found."""
 
-    mock_drive_items.children.get = AsyncMock(return_value=[])
+    mock_onedrive_client.list_drive_items.return_value = []
     backup_id = BACKUP_METADATA["backup_id"]
     client = await hass_ws_client(hass)
     await client.send_json_auto_id({"type": "backup/details", "backup_id": backup_id})
@@ -468,13 +319,13 @@ async def test_agents_backup_not_found(
 async def test_reauth_on_403(
     hass: HomeAssistant,
     hass_ws_client: WebSocketGenerator,
-    mock_drive_items: MagicMock,
+    mock_onedrive_client: MagicMock,
     mock_config_entry: MockConfigEntry,
 ) -> None:
     """Test we re-authenticate on 403."""
 
-    mock_drive_items.children.get = AsyncMock(
-        side_effect=APIError(response_status_code=403)
+    mock_onedrive_client.list_drive_items.side_effect = AuthenticationError(
+        403, "Auth failed"
     )
     backup_id = BACKUP_METADATA["backup_id"]
     client = await hass_ws_client(hass)
@@ -483,7 +334,7 @@ async def test_reauth_on_403(
 
     assert response["success"]
     assert response["result"]["agent_errors"] == {
-        f"{DOMAIN}.{mock_config_entry.unique_id}": "Backup operation failed"
+        f"{DOMAIN}.{mock_config_entry.unique_id}": "Authentication error"
     }
 
     await hass.async_block_till_done()
diff --git a/tests/components/onedrive/test_config_flow.py b/tests/components/onedrive/test_config_flow.py
index 8be6aadfd0f54348090a663f8d5adf7cfe1c5a1c..9acfd8ada3ce17a2615c90252ae346231cbbe708 100644
--- a/tests/components/onedrive/test_config_flow.py
+++ b/tests/components/onedrive/test_config_flow.py
@@ -3,8 +3,7 @@
 from http import HTTPStatus
 from unittest.mock import AsyncMock, MagicMock
 
-from httpx import Response
-from kiota_abstractions.api_error import APIError
+from onedrive_personal_sdk.exceptions import OneDriveException
 import pytest
 
 from homeassistant import config_entries
@@ -20,7 +19,7 @@ from homeassistant.data_entry_flow import FlowResultType
 from homeassistant.helpers import config_entry_oauth2_flow
 
 from . import setup_integration
-from .const import CLIENT_ID
+from .const import CLIENT_ID, MOCK_APPROOT
 
 from tests.common import MockConfigEntry
 from tests.test_util.aiohttp import AiohttpClientMocker
@@ -89,25 +88,52 @@ async def test_full_flow(
     assert result["data"][CONF_TOKEN]["refresh_token"] == "mock-refresh-token"
 
 
+@pytest.mark.usefixtures("current_request_with_host")
+async def test_full_flow_with_owner_not_found(
+    hass: HomeAssistant,
+    hass_client_no_auth: ClientSessionGenerator,
+    aioclient_mock: AiohttpClientMocker,
+    mock_setup_entry: AsyncMock,
+    mock_onedrive_client: MagicMock,
+) -> None:
+    """Ensure we get a default title if the drive's owner can't be read."""
+
+    mock_onedrive_client.get_approot.return_value.created_by.user = None
+
+    result = await hass.config_entries.flow.async_init(
+        DOMAIN, context={"source": config_entries.SOURCE_USER}
+    )
+    await _do_get_token(hass, result, hass_client_no_auth, aioclient_mock)
+    result = await hass.config_entries.flow.async_configure(result["flow_id"])
+
+    assert result["type"] is FlowResultType.CREATE_ENTRY
+    assert len(hass.config_entries.async_entries(DOMAIN)) == 1
+    assert len(mock_setup_entry.mock_calls) == 1
+    assert result["title"] == "OneDrive"
+    assert result["result"].unique_id == "mock_drive_id"
+    assert result["data"][CONF_TOKEN][CONF_ACCESS_TOKEN] == "mock-access-token"
+    assert result["data"][CONF_TOKEN]["refresh_token"] == "mock-refresh-token"
+
+
 @pytest.mark.usefixtures("current_request_with_host")
 @pytest.mark.parametrize(
     ("exception", "error"),
     [
         (Exception, "unknown"),
-        (APIError, "connection_error"),
+        (OneDriveException, "connection_error"),
     ],
 )
 async def test_flow_errors(
     hass: HomeAssistant,
     hass_client_no_auth: ClientSessionGenerator,
     aioclient_mock: AiohttpClientMocker,
-    mock_adapter: MagicMock,
+    mock_onedrive_client: MagicMock,
     exception: Exception,
     error: str,
 ) -> None:
     """Test errors during flow."""
 
-    mock_adapter.get_http_response_message.side_effect = exception
+    mock_onedrive_client.get_approot.side_effect = exception
 
     result = await hass.config_entries.flow.async_init(
         DOMAIN, context={"source": config_entries.SOURCE_USER}
@@ -172,15 +198,12 @@ async def test_reauth_flow_id_changed(
     aioclient_mock: AiohttpClientMocker,
     mock_setup_entry: AsyncMock,
     mock_config_entry: MockConfigEntry,
-    mock_adapter: MagicMock,
+    mock_onedrive_client: MagicMock,
 ) -> None:
     """Test that the reauth flow fails on a different drive id."""
-    mock_adapter.get_http_response_message.return_value = Response(
-        status_code=200,
-        json={
-            "parentReference": {"driveId": "other_drive_id"},
-        },
-    )
+    app_root = MOCK_APPROOT
+    app_root.parent_reference.drive_id = "other_drive_id"
+    mock_onedrive_client.get_approot.return_value = app_root
 
     await setup_integration(hass, mock_config_entry)
 
diff --git a/tests/components/onedrive/test_init.py b/tests/components/onedrive/test_init.py
index bc5c22c3ce6ab5afe4b2f4b2aa5e84e576864793..674bc2d38d97ad8f1a6afaa461b90f784f13eabf 100644
--- a/tests/components/onedrive/test_init.py
+++ b/tests/components/onedrive/test_init.py
@@ -2,7 +2,7 @@
 
 from unittest.mock import MagicMock
 
-from kiota_abstractions.api_error import APIError
+from onedrive_personal_sdk.exceptions import AuthenticationError, OneDriveException
 import pytest
 
 from homeassistant.config_entries import ConfigEntryState
@@ -31,82 +31,31 @@ async def test_load_unload_config_entry(
 @pytest.mark.parametrize(
     ("side_effect", "state"),
     [
-        (APIError(response_status_code=403), ConfigEntryState.SETUP_ERROR),
-        (APIError(response_status_code=500), ConfigEntryState.SETUP_RETRY),
+        (AuthenticationError(403, "Auth failed"), ConfigEntryState.SETUP_ERROR),
+        (OneDriveException(), ConfigEntryState.SETUP_RETRY),
     ],
 )
 async def test_approot_errors(
     hass: HomeAssistant,
     mock_config_entry: MockConfigEntry,
-    mock_get_special_folder: MagicMock,
+    mock_onedrive_client: MagicMock,
     side_effect: Exception,
     state: ConfigEntryState,
 ) -> None:
     """Test errors during approot retrieval."""
-    mock_get_special_folder.side_effect = side_effect
+    mock_onedrive_client.get_approot.side_effect = side_effect
     await setup_integration(hass, mock_config_entry)
     assert mock_config_entry.state is state
 
 
-async def test_faulty_approot(
+async def test_get_integration_folder_error(
     hass: HomeAssistant,
     mock_config_entry: MockConfigEntry,
-    mock_get_special_folder: MagicMock,
+    mock_onedrive_client: MagicMock,
     caplog: pytest.LogCaptureFixture,
 ) -> None:
     """Test faulty approot retrieval."""
-    mock_get_special_folder.return_value = None
-    await setup_integration(hass, mock_config_entry)
-    assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
-    assert "Failed to get approot folder" in caplog.text
-
-
-async def test_faulty_integration_folder(
-    hass: HomeAssistant,
-    mock_config_entry: MockConfigEntry,
-    mock_drive_items: MagicMock,
-    caplog: pytest.LogCaptureFixture,
-) -> None:
-    """Test faulty approot retrieval."""
-    mock_drive_items.get.return_value = None
+    mock_onedrive_client.create_folder.side_effect = OneDriveException()
     await setup_integration(hass, mock_config_entry)
     assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
     assert "Failed to get backups_9f86d081 folder" in caplog.text
-
-
-async def test_500_error_during_backup_folder_get(
-    hass: HomeAssistant,
-    mock_config_entry: MockConfigEntry,
-    mock_drive_items: MagicMock,
-    caplog: pytest.LogCaptureFixture,
-) -> None:
-    """Test error during backup folder creation."""
-    mock_drive_items.get.side_effect = APIError(response_status_code=500)
-    await setup_integration(hass, mock_config_entry)
-    assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
-    assert "Failed to get backups_9f86d081 folder" in caplog.text
-
-
-async def test_error_during_backup_folder_creation(
-    hass: HomeAssistant,
-    mock_config_entry: MockConfigEntry,
-    mock_drive_items: MagicMock,
-    caplog: pytest.LogCaptureFixture,
-) -> None:
-    """Test error during backup folder creation."""
-    mock_drive_items.get.side_effect = APIError(response_status_code=404)
-    mock_drive_items.children.post.side_effect = APIError()
-    await setup_integration(hass, mock_config_entry)
-    assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
-    assert "Failed to create backups_9f86d081 folder" in caplog.text
-
-
-async def test_successful_backup_folder_creation(
-    hass: HomeAssistant,
-    mock_config_entry: MockConfigEntry,
-    mock_drive_items: MagicMock,
-) -> None:
-    """Test successful backup folder creation."""
-    mock_drive_items.get.side_effect = APIError(response_status_code=404)
-    await setup_integration(hass, mock_config_entry)
-    assert mock_config_entry.state is ConfigEntryState.LOADED