diff --git a/appinfo/routes/routesSettingsController.php b/appinfo/routes/routesSettingsController.php
index b707fcf5c3e..bf68431792f 100644
--- a/appinfo/routes/routesSettingsController.php
+++ b/appinfo/routes/routesSettingsController.php
@@ -16,5 +16,7 @@
 		['name' => 'Settings#setSIPSettings', 'url' => '/api/{apiVersion}/settings/sip', 'verb' => 'POST', 'requirements' => $requirements],
 		/** @see \OCA\Talk\Controller\SettingsController::setUserSetting() */
 		['name' => 'Settings#setUserSetting', 'url' => '/api/{apiVersion}/settings/user', 'verb' => 'POST', 'requirements' => $requirements],
+		/** @see \OCA\Talk\Controller\SettingsController::getPersonalCalendars() */
+		['name' => 'Settings#getPersonalCalendars', 'url' => '/api/{apiVersion}/personal-calendars', 'verb' => 'GET', 'requirements' => $requirements],
 	],
 ];
diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php
index 55c90506f22..7e2e53e6e9a 100644
--- a/lib/Controller/SettingsController.php
+++ b/lib/Controller/SettingsController.php
@@ -8,29 +8,38 @@
 
 namespace OCA\Talk\Controller;
 
+use OCA\Talk\ResponseDefinitions;
 use OCA\Talk\Settings\BeforePreferenceSetEventListener;
 use OCP\AppFramework\Http;
 use OCP\AppFramework\Http\Attribute\NoAdminRequired;
 use OCP\AppFramework\Http\Attribute\OpenAPI;
 use OCP\AppFramework\Http\DataResponse;
 use OCP\AppFramework\OCSController;
+use OCP\Calendar\IManager;
+use OCP\Constants;
 use OCP\Files\IRootFolder;
 use OCP\IConfig;
+use OCP\IDBConnection;
 use OCP\IGroup;
 use OCP\IGroupManager;
 use OCP\IRequest;
 use Psr\Log\LoggerInterface;
 
+/**
+ * @psalm-import-type TalkCalendar from ResponseDefinitions
+ */
 class SettingsController extends OCSController {
 
 	public function __construct(
 		string $appName,
 		IRequest $request,
 		protected IRootFolder $rootFolder,
+		protected IDBConnection $db,
 		protected IConfig $config,
 		protected IGroupManager $groupManager,
 		protected LoggerInterface $logger,
 		protected BeforePreferenceSetEventListener $preferenceListener,
+		protected IManager $calendarManager,
 		protected ?string $userId,
 	) {
 		parent::__construct($appName, $request);
@@ -86,4 +95,81 @@ public function setSIPSettings(
 
 		return new DataResponse(null);
 	}
+
+	/**
+	 * Get writable calendars and the default calendar
+	 *
+	 * Required capability: `schedule-meeting`
+	 *
+	 * @return DataResponse<Http::STATUS_OK, array{defaultCalendarUri: ?string, calendars: list<TalkCalendar>}, array{}>
+	 *
+	 * 200: Get a list of calendars
+	 */
+	#[NoAdminRequired]
+	public function getPersonalCalendars(): DataResponse {
+		$calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $this->userId);
+
+		$defaultCalendarUri = $selectedCalendarUri = null;
+		$selectedCalendar = $this->getSchedulingCalendarFromPropertiesTable($this->userId);
+		if ($selectedCalendar !== false) {
+			$parts = explode('/', rtrim($selectedCalendar, '/'));
+			if (count($parts) === 3 && $parts[0] === 'calendars' && $parts[1] === $this->userId) {
+				$selectedCalendarUri = $parts[2];
+			}
+		}
+
+		$hasPersonal = false;
+		$list = [];
+		foreach ($calendars as $calendar) {
+			if ($calendar->isDeleted()) {
+				continue;
+			}
+
+			if (!($calendar->getPermissions() & Constants::PERMISSION_CREATE)) {
+				continue;
+			}
+
+			if ($calendar->getUri() === 'personal') {
+				$hasPersonal = true;
+			}
+
+			if ($selectedCalendarUri === $calendar->getUri()) {
+				$defaultCalendarUri = $selectedCalendarUri;
+			}
+
+			$list[] = [
+				'uri' => $calendar->getUri(),
+				'name' => $calendar->getDisplayName() ?? $calendar->getUri(),
+				'color' => $calendar->getDisplayColor(),
+			];
+		}
+
+		return new DataResponse([
+			'defaultCalendarUri' => $defaultCalendarUri ?? ($hasPersonal ? 'personal' : null),
+			'calendars' => $list,
+		]);
+	}
+
+	/**
+	 * @param string $userId
+	 * @return false|string
+	 */
+	protected function getSchedulingCalendarFromPropertiesTable(string $userId) {
+		$propertyPath = 'principals/users/' . $userId;
+		$propertyName = '{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL';
+
+		$query = $this->db->getQueryBuilder();
+		$query->select('propertyvalue')
+			->from('properties')
+			->where($query->expr()->eq('userid', $query->createNamedParameter($userId)))
+			->andWhere($query->expr()->eq('propertypath', $query->createNamedParameter($propertyPath)))
+			->andWhere($query->expr()->eq('propertyname', $query->createNamedParameter($propertyName)))
+			->setMaxResults(1);
+
+		$result = $query->executeQuery();
+		$property = $result->fetchOne();
+		$result->closeCursor();
+
+		return $property;
+	}
 }
diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php
index 60da06cf6cb..8651e2b1629 100644
--- a/lib/ResponseDefinitions.php
+++ b/lib/ResponseDefinitions.php
@@ -44,6 +44,12 @@
  *     secret: string,
  * }
  *
+ * @psalm-type TalkCalendar = array{
+ *     uri: string,
+ *     name: string,
+ *     color: ?string,
+ * }
+ *
  * @psalm-type TalkCallPeer = array{
  *     actorId: string,
  *     actorType: string,
diff --git a/openapi-full.json b/openapi-full.json
index eccc60c132b..d29a3090815 100644
--- a/openapi-full.json
+++ b/openapi-full.json
@@ -207,6 +207,26 @@
                     }
                 ]
             },
+            "Calendar": {
+                "type": "object",
+                "required": [
+                    "uri",
+                    "name",
+                    "color"
+                ],
+                "properties": {
+                    "uri": {
+                        "type": "string"
+                    },
+                    "name": {
+                        "type": "string"
+                    },
+                    "color": {
+                        "type": "string",
+                        "nullable": true
+                    }
+                }
+            },
             "CallPeer": {
                 "type": "object",
                 "required": [
@@ -17680,6 +17700,96 @@
                 }
             }
         },
+        "/ocs/v2.php/apps/spreed/api/{apiVersion}/personal-calendars": {
+            "get": {
+                "operationId": "settings-get-personal-calendars",
+                "summary": "Get writable calendars and the default calendar",
+                "description": "Required capability: `schedule-meeting`",
+                "tags": [
+                    "settings"
+                ],
+                "security": [
+                    {
+                        "bearer_auth": []
+                    },
+                    {
+                        "basic_auth": []
+                    }
+                ],
+                "parameters": [
+                    {
+                        "name": "apiVersion",
+                        "in": "path",
+                        "required": true,
+                        "schema": {
+                            "type": "string",
+                            "enum": [
+                                "v1"
+                            ],
+                            "default": "v1"
+                        }
+                    },
+                    {
+                        "name": "OCS-APIRequest",
+                        "in": "header",
+                        "description": "Required to be true for the API request to pass",
+                        "required": true,
+                        "schema": {
+                            "type": "boolean",
+                            "default": true
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Get a list of calendars",
+                        "content": {
+                            "application/json": {
+                                "schema": {
+                                    "type": "object",
+                                    "required": [
+                                        "ocs"
+                                    ],
+                                    "properties": {
+                                        "ocs": {
+                                            "type": "object",
+                                            "required": [
+                                                "meta",
+                                                "data"
+                                            ],
+                                            "properties": {
+                                                "meta": {
+                                                    "$ref": "#/components/schemas/OCSMeta"
+                                                },
+                                                "data": {
+                                                    "type": "object",
+                                                    "required": [
+                                                        "defaultCalendarUri",
+                                                        "calendars"
+                                                    ],
+                                                    "properties": {
+                                                        "defaultCalendarUri": {
+                                                            "type": "string",
+                                                            "nullable": true
+                                                        },
+                                                        "calendars": {
+                                                            "type": "array",
+                                                            "items": {
+                                                                "$ref": "#/components/schemas/Calendar"
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
         "/ocs/v2.php/apps/spreed/api/{apiVersion}/signaling/settings": {
             "get": {
                 "operationId": "signaling-get-settings",
diff --git a/openapi.json b/openapi.json
index e00793473bf..87108cfd7af 100644
--- a/openapi.json
+++ b/openapi.json
@@ -148,6 +148,26 @@
                     }
                 }
             },
+            "Calendar": {
+                "type": "object",
+                "required": [
+                    "uri",
+                    "name",
+                    "color"
+                ],
+                "properties": {
+                    "uri": {
+                        "type": "string"
+                    },
+                    "name": {
+                        "type": "string"
+                    },
+                    "color": {
+                        "type": "string",
+                        "nullable": true
+                    }
+                }
+            },
             "CallPeer": {
                 "type": "object",
                 "required": [
@@ -17820,6 +17840,96 @@
                 }
             }
         },
+        "/ocs/v2.php/apps/spreed/api/{apiVersion}/personal-calendars": {
+            "get": {
+                "operationId": "settings-get-personal-calendars",
+                "summary": "Get writable calendars and the default calendar",
+                "description": "Required capability: `schedule-meeting`",
+                "tags": [
+                    "settings"
+                ],
+                "security": [
+                    {
+                        "bearer_auth": []
+                    },
+                    {
+                        "basic_auth": []
+                    }
+                ],
+                "parameters": [
+                    {
+                        "name": "apiVersion",
+                        "in": "path",
+                        "required": true,
+                        "schema": {
+                            "type": "string",
+                            "enum": [
+                                "v1"
+                            ],
+                            "default": "v1"
+                        }
+                    },
+                    {
+                        "name": "OCS-APIRequest",
+                        "in": "header",
+                        "description": "Required to be true for the API request to pass",
+                        "required": true,
+                        "schema": {
+                            "type": "boolean",
+                            "default": true
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Get a list of calendars",
+                        "content": {
+                            "application/json": {
+                                "schema": {
+                                    "type": "object",
+                                    "required": [
+                                        "ocs"
+                                    ],
+                                    "properties": {
+                                        "ocs": {
+                                            "type": "object",
+                                            "required": [
+                                                "meta",
+                                                "data"
+                                            ],
+                                            "properties": {
+                                                "meta": {
+                                                    "$ref": "#/components/schemas/OCSMeta"
+                                                },
+                                                "data": {
+                                                    "type": "object",
+                                                    "required": [
+                                                        "defaultCalendarUri",
+                                                        "calendars"
+                                                    ],
+                                                    "properties": {
+                                                        "defaultCalendarUri": {
+                                                            "type": "string",
+                                                            "nullable": true
+                                                        },
+                                                        "calendars": {
+                                                            "type": "array",
+                                                            "items": {
+                                                                "$ref": "#/components/schemas/Calendar"
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
         "/ocs/v2.php/apps/spreed/api/{apiVersion}/signaling/settings": {
             "get": {
                 "operationId": "signaling-get-settings",
diff --git a/src/types/openapi/openapi-full.ts b/src/types/openapi/openapi-full.ts
index eafe8a13943..e2bca6e0a55 100644
--- a/src/types/openapi/openapi-full.ts
+++ b/src/types/openapi/openapi-full.ts
@@ -1367,6 +1367,26 @@ export type paths = {
         patch?: never;
         trace?: never;
     };
+    "/ocs/v2.php/apps/spreed/api/{apiVersion}/personal-calendars": {
+        parameters: {
+            query?: never;
+            header?: never;
+            path?: never;
+            cookie?: never;
+        };
+        /**
+         * Get writable calendars and the default calendar
+         * @description Required capability: `schedule-meeting`
+         */
+        get: operations["settings-get-personal-calendars"];
+        put?: never;
+        post?: never;
+        delete?: never;
+        options?: never;
+        head?: never;
+        patch?: never;
+        trace?: never;
+    };
     "/ocs/v2.php/apps/spreed/api/{apiVersion}/signaling/settings": {
         parameters: {
             query?: never;
@@ -1965,6 +1985,11 @@ export type components = {
         BotWithDetailsAndSecret: components["schemas"]["BotWithDetails"] & {
             secret: string;
         };
+        Calendar: {
+            uri: string;
+            name: string;
+            color: string | null;
+        };
         CallPeer: {
             actorId: string;
             actorType: string;
@@ -8719,6 +8744,39 @@ export interface operations {
             };
         };
     };
+    "settings-get-personal-calendars": {
+        parameters: {
+            query?: never;
+            header: {
+                /** @description Required to be true for the API request to pass */
+                "OCS-APIRequest": boolean;
+            };
+            path: {
+                apiVersion: "v1";
+            };
+            cookie?: never;
+        };
+        requestBody?: never;
+        responses: {
+            /** @description Get a list of calendars */
+            200: {
+                headers: {
+                    [name: string]: unknown;
+                };
+                content: {
+                    "application/json": {
+                        ocs: {
+                            meta: components["schemas"]["OCSMeta"];
+                            data: {
+                                defaultCalendarUri: string | null;
+                                calendars: components["schemas"]["Calendar"][];
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
     "signaling-get-settings": {
         parameters: {
             query?: {
diff --git a/src/types/openapi/openapi.ts b/src/types/openapi/openapi.ts
index 6a208fd0f90..5ce5d8a462a 100644
--- a/src/types/openapi/openapi.ts
+++ b/src/types/openapi/openapi.ts
@@ -1369,6 +1369,26 @@ export type paths = {
         patch?: never;
         trace?: never;
     };
+    "/ocs/v2.php/apps/spreed/api/{apiVersion}/personal-calendars": {
+        parameters: {
+            query?: never;
+            header?: never;
+            path?: never;
+            cookie?: never;
+        };
+        /**
+         * Get writable calendars and the default calendar
+         * @description Required capability: `schedule-meeting`
+         */
+        get: operations["settings-get-personal-calendars"];
+        put?: never;
+        post?: never;
+        delete?: never;
+        options?: never;
+        head?: never;
+        patch?: never;
+        trace?: never;
+    };
     "/ocs/v2.php/apps/spreed/api/{apiVersion}/signaling/settings": {
         parameters: {
             query?: never;
@@ -1462,6 +1482,11 @@ export type components = {
             /** Format: int64 */
             state: number;
         };
+        Calendar: {
+            uri: string;
+            name: string;
+            color: string | null;
+        };
         CallPeer: {
             actorId: string;
             actorType: string;
@@ -8300,6 +8325,39 @@ export interface operations {
             };
         };
     };
+    "settings-get-personal-calendars": {
+        parameters: {
+            query?: never;
+            header: {
+                /** @description Required to be true for the API request to pass */
+                "OCS-APIRequest": boolean;
+            };
+            path: {
+                apiVersion: "v1";
+            };
+            cookie?: never;
+        };
+        requestBody?: never;
+        responses: {
+            /** @description Get a list of calendars */
+            200: {
+                headers: {
+                    [name: string]: unknown;
+                };
+                content: {
+                    "application/json": {
+                        ocs: {
+                            meta: components["schemas"]["OCSMeta"];
+                            data: {
+                                defaultCalendarUri: string | null;
+                                calendars: components["schemas"]["Calendar"][];
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
     "signaling-get-settings": {
         parameters: {
             query?: {