diff --git a/tests/conftest.py b/tests/conftest.py
index 4562ce9..33aa1f2 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -9,6 +9,7 @@
     DEFAULT_COLLABORATORS_RESPONSE,
     DEFAULT_COMMENT_RESPONSE,
     DEFAULT_COMMENTS_RESPONSE,
+    DEFAULT_COMPLETED_ITEMS_RESPONSE,
     DEFAULT_LABEL_RESPONSE,
     DEFAULT_LABELS_RESPONSE,
     DEFAULT_PROJECT_RESPONSE,
@@ -25,6 +26,7 @@
     AuthResult,
     Collaborator,
     Comment,
+    CompletedItems,
     Label,
     Project,
     QuickAddResult,
@@ -177,3 +179,13 @@ def default_auth_response() -> Dict[str, Any]:
 @pytest.fixture()
 def default_auth_result() -> AuthResult:
     return AuthResult.from_dict(DEFAULT_AUTH_RESPONSE)
+
+
+@pytest.fixture()
+def default_completed_items_response() -> dict[str, Any]:
+    return DEFAULT_COMPLETED_ITEMS_RESPONSE
+
+
+@pytest.fixture()
+def default_completed_items() -> CompletedItems:
+    return CompletedItems.from_dict(DEFAULT_COMPLETED_ITEMS_RESPONSE)
diff --git a/tests/data/test_defaults.py b/tests/data/test_defaults.py
index cbb8907..ade3b96 100644
--- a/tests/data/test_defaults.py
+++ b/tests/data/test_defaults.py
@@ -1,4 +1,5 @@
 from __future__ import annotations
+
 from typing import Any
 
 REST_API_BASE_URL = "https://api.todoist.com/rest/v2"
@@ -148,3 +149,32 @@
     "access_token": "1234",
     "state": "somestate",
 }
+
+DEFAULT_ITEM_RESPONSE = {
+    "id": "2995104339",
+    "user_id": "2671355",
+    "project_id": "2203306141",
+    "content": "Buy Milk",
+    "description": "",
+    "priority": 1,
+    "due": DEFAULT_DUE_RESPONSE,
+    "child_order": 1,
+    "day_order": -1,
+    "collapsed": False,
+    "labels": ["Food", "Shopping"],
+    "added_by_uid": "2671355",
+    "assigned_by_uid": "2671355",
+    "checked": False,
+    "is_deleted": False,
+    "added_at": "2014-09-26T08:25:05.000000Z",
+}
+
+DEFAULT_ITEM_COMPLETED_INFO_RESPONSE = {"item_id": "2995104339", "completed_items": 12}
+
+DEFAULT_COMPLETED_ITEMS_RESPONSE = {
+    "items": [DEFAULT_ITEM_RESPONSE],
+    "completed_info": [DEFAULT_ITEM_COMPLETED_INFO_RESPONSE],
+    "total": 22,
+    "next_cursor": "k85gVI5ZAs8AAAABFoOzAQ",
+    "has_more": True,
+}
diff --git a/tests/test_api_items.py b/tests/test_api_items.py
new file mode 100644
index 0000000..6f2acac
--- /dev/null
+++ b/tests/test_api_items.py
@@ -0,0 +1,64 @@
+from typing import Any
+from urllib.parse import parse_qs, urlparse
+
+import pytest
+import responses
+
+from tests.data.test_defaults import SYNC_API_BASE_URL
+from tests.utils.test_utils import assert_auth_header
+from todoist_api_python.api import TodoistAPI
+from todoist_api_python.api_async import TodoistAPIAsync
+from todoist_api_python.endpoints import COMPLETED_ITEMS_ENDPOINT
+from todoist_api_python.models import CompletedItems
+
+
+@pytest.mark.asyncio
+async def test_get_completed_items(
+    todoist_api: TodoistAPI,
+    todoist_api_async: TodoistAPIAsync,
+    requests_mock: responses.RequestsMock,
+    default_completed_items_response: dict[str, Any],
+    default_completed_items: CompletedItems,
+) -> None:
+    project_id = "1234"
+    section_id = "5678"
+    item_id = "90ab"
+    last_seen_id = "cdef"
+    limit = 30
+    cursor = "ghij"
+
+    def assert_query(url):
+        queries = parse_qs(urlparse(url).query)
+        assert queries.get("project_id") == [project_id]
+        assert queries.get("section_id") == [section_id]
+        assert queries.get("item_id") == [item_id]
+        assert queries.get("last_seen_id") == [last_seen_id]
+        assert queries.get("limit") == [str(limit)]
+        assert queries.get("cursor") == [cursor]
+
+    expected_endpoint = f"{SYNC_API_BASE_URL}/{COMPLETED_ITEMS_ENDPOINT}"
+
+    requests_mock.add(
+        responses.GET,
+        expected_endpoint,
+        json=default_completed_items_response,
+        status=200,
+    )
+
+    completed_items = todoist_api.get_completed_items(
+        project_id, section_id, item_id, last_seen_id, limit, cursor
+    )
+
+    assert len(requests_mock.calls) == 1
+    assert_auth_header(requests_mock.calls[0].request)
+    assert_query(requests_mock.calls[0].request.url)
+    assert completed_items == default_completed_items
+
+    completed_items = await todoist_api_async.get_completed_items(
+        project_id, section_id, item_id, last_seen_id, limit, cursor
+    )
+
+    assert len(requests_mock.calls) == 2
+    assert_auth_header(requests_mock.calls[1].request)
+    assert_query(requests_mock.calls[1].request.url)
+    assert completed_items == default_completed_items
diff --git a/tests/test_models.py b/tests/test_models.py
index ad6115d..06cf35b 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -6,7 +6,10 @@
     DEFAULT_ATTACHMENT_RESPONSE,
     DEFAULT_COLLABORATOR_RESPONSE,
     DEFAULT_COMMENT_RESPONSE,
+    DEFAULT_COMPLETED_ITEMS_RESPONSE,
     DEFAULT_DUE_RESPONSE,
+    DEFAULT_ITEM_COMPLETED_INFO_RESPONSE,
+    DEFAULT_ITEM_RESPONSE,
     DEFAULT_LABEL_RESPONSE,
     DEFAULT_PROJECT_RESPONSE,
     DEFAULT_SECTION_RESPONSE,
@@ -17,7 +20,10 @@
     AuthResult,
     Collaborator,
     Comment,
+    CompletedItems,
     Due,
+    Item,
+    ItemCompletedInfo,
     Label,
     Project,
     QuickAddResult,
@@ -280,3 +286,87 @@ def test_auth_result_from_dict():
 
     assert auth_result.access_token == token
     assert auth_result.state == state
+
+
+def test_item_from_dict():
+    sample_data = dict(DEFAULT_ITEM_RESPONSE)
+    sample_data.update(unexpected_data)
+
+    item = Item.from_dict(sample_data)
+
+    assert item.id == "2995104339"
+    assert item.user_id == "2671355"
+    assert item.project_id == "2203306141"
+    assert item.content == "Buy Milk"
+    assert item.description == ""
+    assert item.priority == 1
+    assert item.due.date == DEFAULT_DUE_RESPONSE["date"]
+    assert item.due.is_recurring == DEFAULT_DUE_RESPONSE["is_recurring"]
+    assert item.due.string == DEFAULT_DUE_RESPONSE["string"]
+    assert item.due.datetime == DEFAULT_DUE_RESPONSE["datetime"]
+    assert item.due.timezone == DEFAULT_DUE_RESPONSE["timezone"]
+    assert item.parent_id is None
+    assert item.child_order == 1
+    assert item.section_id is None
+    assert item.day_order == -1
+    assert item.collapsed is False
+    assert item.labels == ["Food", "Shopping"]
+    assert item.added_by_uid == "2671355"
+    assert item.assigned_by_uid == "2671355"
+    assert item.responsible_uid is None
+    assert item.checked is False
+    assert item.is_deleted is False
+    assert item.sync_id is None
+    assert item.added_at == "2014-09-26T08:25:05.000000Z"
+
+
+def test_item_completed_info_from_dict():
+    sample_data = dict(DEFAULT_ITEM_COMPLETED_INFO_RESPONSE)
+    sample_data.update(unexpected_data)
+
+    info = ItemCompletedInfo.from_dict(sample_data)
+
+    assert info.item_id == "2995104339"
+    assert info.completed_items == 12
+
+
+def test_completed_items_from_dict():
+    sample_data = dict(DEFAULT_COMPLETED_ITEMS_RESPONSE)
+    sample_data.update(unexpected_data)
+
+    completed_items = CompletedItems.from_dict(sample_data)
+
+    assert completed_items.total == 22
+    assert completed_items.next_cursor == "k85gVI5ZAs8AAAABFoOzAQ"
+    assert completed_items.has_more is True
+    assert len(completed_items.items) == 1
+    assert completed_items.items[0].id == "2995104339"
+    assert completed_items.items[0].user_id == "2671355"
+    assert completed_items.items[0].project_id == "2203306141"
+    assert completed_items.items[0].content == "Buy Milk"
+    assert completed_items.items[0].description == ""
+    assert completed_items.items[0].priority == 1
+    assert completed_items.items[0].due.date == DEFAULT_DUE_RESPONSE["date"]
+    assert (
+        completed_items.items[0].due.is_recurring
+        == DEFAULT_DUE_RESPONSE["is_recurring"]
+    )
+    assert completed_items.items[0].due.string == DEFAULT_DUE_RESPONSE["string"]
+    assert completed_items.items[0].due.datetime == DEFAULT_DUE_RESPONSE["datetime"]
+    assert completed_items.items[0].due.timezone == DEFAULT_DUE_RESPONSE["timezone"]
+    assert completed_items.items[0].parent_id is None
+    assert completed_items.items[0].child_order == 1
+    assert completed_items.items[0].section_id is None
+    assert completed_items.items[0].day_order == -1
+    assert completed_items.items[0].collapsed is False
+    assert completed_items.items[0].labels == ["Food", "Shopping"]
+    assert completed_items.items[0].added_by_uid == "2671355"
+    assert completed_items.items[0].assigned_by_uid == "2671355"
+    assert completed_items.items[0].responsible_uid is None
+    assert completed_items.items[0].checked is False
+    assert completed_items.items[0].is_deleted is False
+    assert completed_items.items[0].sync_id is None
+    assert completed_items.items[0].added_at == "2014-09-26T08:25:05.000000Z"
+    assert len(completed_items.completed_info) == 1
+    assert completed_items.completed_info[0].item_id == "2995104339"
+    assert completed_items.completed_info[0].completed_items == 12
diff --git a/todoist_api_python/api.py b/todoist_api_python/api.py
index 96d1769..fa727ab 100644
--- a/todoist_api_python/api.py
+++ b/todoist_api_python/api.py
@@ -7,6 +7,7 @@
 from todoist_api_python.endpoints import (
     COLLABORATORS_ENDPOINT,
     COMMENTS_ENDPOINT,
+    COMPLETED_ITEMS_ENDPOINT,
     LABELS_ENDPOINT,
     PROJECTS_ENDPOINT,
     QUICK_ADD_ENDPOINT,
@@ -22,6 +23,7 @@
 from todoist_api_python.models import (
     Collaborator,
     Comment,
+    CompletedItems,
     Label,
     Project,
     QuickAddResult,
@@ -207,3 +209,28 @@ def remove_shared_label(self, name: str) -> bool:
         endpoint = get_rest_url(SHARED_LABELS_REMOVE_ENDPOINT)
         data = {"name": name}
         return post(self._session, endpoint, self._token, data=data)
+
+    def get_completed_items(
+        self,
+        project_id: str | None = None,
+        section_id: str | None = None,
+        item_id: str | None = None,
+        last_seen_id: str | None = None,
+        limit: int | None = None,
+        cursor: str | None = None,
+    ) -> CompletedItems:
+        endpoint = get_sync_url(COMPLETED_ITEMS_ENDPOINT)
+        completed_items = get(
+            self._session,
+            endpoint,
+            self._token,
+            {
+                "project_id": project_id,
+                "section_id": section_id,
+                "item_id": item_id,
+                "last_seen_id": last_seen_id,
+                "limit": limit,
+                "cursor": cursor,
+            },
+        )
+        return CompletedItems.from_dict(completed_items)
diff --git a/todoist_api_python/api_async.py b/todoist_api_python/api_async.py
index c9e83f5..999b65f 100644
--- a/todoist_api_python/api_async.py
+++ b/todoist_api_python/api_async.py
@@ -6,6 +6,7 @@
 from todoist_api_python.models import (
     Collaborator,
     Comment,
+    CompletedItems,
     Label,
     Project,
     QuickAddResult,
@@ -120,3 +121,18 @@ async def rename_shared_label(self, name: str, new_name: str) -> bool:
 
     async def remove_shared_label(self, name: str) -> bool:
         return await run_async(lambda: self._api.remove_shared_label(name))
+
+    async def get_completed_items(
+        self,
+        project_id: str | None = None,
+        section_id: str | None = None,
+        item_id: str | None = None,
+        last_seen_id: str | None = None,
+        limit: int | None = None,
+        cursor: str | None = None,
+    ) -> CompletedItems:
+        return await run_async(
+            lambda: self._api.get_completed_items(
+                project_id, section_id, item_id, last_seen_id, limit, cursor
+            )
+        )
diff --git a/todoist_api_python/endpoints.py b/todoist_api_python/endpoints.py
index e5a32be..da7c504 100644
--- a/todoist_api_python/endpoints.py
+++ b/todoist_api_python/endpoints.py
@@ -24,6 +24,8 @@
 TOKEN_ENDPOINT = "oauth/access_token"
 REVOKE_TOKEN_ENDPOINT = "access_tokens/revoke"
 
+COMPLETED_ITEMS_ENDPOINT = "archive/items"
+
 
 def get_rest_url(relative_path: str) -> str:
     return urljoin(REST_API, relative_path)
diff --git a/todoist_api_python/models.py b/todoist_api_python/models.py
index 5c478f0..7a78719 100644
--- a/todoist_api_python/models.py
+++ b/todoist_api_python/models.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 
-from dataclasses import dataclass
-from typing import List, Literal
+from dataclasses import dataclass, fields
+from typing import Any, List, Literal
 
 from todoist_api_python.utils import get_url_for_task
 
@@ -357,3 +357,67 @@ def from_dict(cls, obj):
             access_token=obj["access_token"],
             state=obj["state"],
         )
+
+
+@dataclass
+class Item:
+    id: str
+    user_id: str
+    project_id: str
+    content: str
+    description: str
+    priority: int
+    child_order: int
+    collapsed: bool
+    labels: list[str]
+    checked: bool
+    is_deleted: bool
+    added_at: str
+    due: Due | None = None
+    parent_id: int | None = None
+    section_id: str | None = None
+    day_order: int | None = None
+    added_by_uid: str | None = None
+    assigned_by_uid: str | None = None
+    responsible_uid: str | None = None
+    sync_id: str | None = None
+    completed_at: str | None = None
+
+    @classmethod
+    def from_dict(cls, obj: dict[str, Any]) -> Item:
+        params = {f.name: obj[f.name] for f in fields(cls) if f.name in obj}
+        if (due := obj.get("due")) is not None:
+            params["due"] = Due.from_dict(due)
+
+        return cls(**params)
+
+
+@dataclass
+class ItemCompletedInfo:
+    item_id: str
+    completed_items: int
+
+    @classmethod
+    def from_dict(cls, obj: dict[str, Any]) -> ItemCompletedInfo:
+        return cls(**{f.name: obj[f.name] for f in fields(cls)})
+
+
+@dataclass
+class CompletedItems:
+    items: list[Item]
+    total: int
+    completed_info: list[ItemCompletedInfo]
+    has_more: bool
+    next_cursor: str | None = None
+
+    @classmethod
+    def from_dict(cls, obj: dict[str, Any]) -> CompletedItems:
+        return cls(
+            items=[Item.from_dict(v) for v in obj["items"]],
+            total=obj["total"],
+            completed_info=[
+                ItemCompletedInfo.from_dict(v) for v in obj["completed_info"]
+            ],
+            has_more=obj["has_more"],
+            next_cursor=obj.get("next_cursor"),
+        )