diff --git a/packages/comty.js/src/models/music/index.js b/packages/comty.js/src/models/music/index.js
index 7bdbc626..61e73d5d 100644
--- a/packages/comty.js/src/models/music/index.js
+++ b/packages/comty.js/src/models/music/index.js
@@ -14,4 +14,24 @@ export default class MusicModel {
 
         return data
     }
+
+    static search = async (keywords, {
+        limit = 5,
+        offset = 0,
+        useTidal = false,
+    }) => {
+        const { data } = await request({
+            instance: MusicModel.api_instance,
+            method: "GET",
+            url: `/search`,
+            params: {
+                keywords,
+                limit,
+                offset,
+                useTidal,
+            }
+        })
+
+        return data
+    }
 }
\ No newline at end of file
diff --git a/packages/comty.js/src/models/sync/index.js b/packages/comty.js/src/models/sync/index.js
index 43bcbf0c..8ee70c43 100755
--- a/packages/comty.js/src/models/sync/index.js
+++ b/packages/comty.js/src/models/sync/index.js
@@ -1,11 +1,47 @@
-import SpotifySyncModel from "./cores/spotifyCore"
+import spotifyService from "./services/spotify"
+import tidalService from "./services/tidal"
+
+const namespacesServices = {
+    spotify: spotifyService,
+    tidal: tidalService
+}
 
 export default class SyncModel {
-    static get bridge() {
-        return window.app?.cores.api.withEndpoints()
+    static get spotifyCore() {
+        return namespacesServices.spotify
     }
 
-    static get spotifyCore() {
-        return SpotifySyncModel
+    static get tidalCore() {
+        return namespacesServices.tidal
+    }
+
+    static async linkService(namespace) {
+        const service = namespacesServices[namespace]
+
+        if (!service || typeof service.linkAccount !== "function") {
+            throw new Error(`Service ${namespace} not found or not accepting linking.`)
+        }
+
+        return await service.linkAccount()
+    }
+
+    static async unlinkService(namespace) {
+        const service = namespacesServices[namespace]
+
+        if (!service || typeof service.unlinkAccount !== "function") {
+            throw new Error(`Service ${namespace} not found or not accepting unlinking.`)
+        }
+
+        return await service.unlinkAccount()
+    }
+
+    static async hasServiceLinked(namespace) {
+        const service = namespacesServices[namespace]
+
+        if (!service || typeof service.isActive !== "function") {
+            throw new Error(`Service ${namespace} not found or not accepting linking.`)
+        }
+
+        return await service.isActive()
     }
 }
\ No newline at end of file
diff --git a/packages/comty.js/src/models/sync/cores/spotifyCore.js b/packages/comty.js/src/models/sync/services/spotify.js
similarity index 84%
rename from packages/comty.js/src/models/sync/cores/spotifyCore.js
rename to packages/comty.js/src/models/sync/services/spotify.js
index 82fb2d74..5860e212 100755
--- a/packages/comty.js/src/models/sync/cores/spotifyCore.js
+++ b/packages/comty.js/src/models/sync/services/spotify.js
@@ -28,7 +28,7 @@ export default class SpotifySyncModel {
     }
 
     static async get_client_id() {
-        const { data } = await app.cores.api.customRequest( {
+        const { data } = await app.cores.api.customRequest({
             method: "GET",
             url: `/sync/spotify/client_id`,
         })
@@ -37,7 +37,7 @@ export default class SpotifySyncModel {
     }
 
     static async syncAuthCode(code) {
-        const { data } = await app.cores.api.customRequest( {
+        const { data } = await app.cores.api.customRequest({
             method: "POST",
             url: `/sync/spotify/auth`,
             data: {
@@ -50,7 +50,7 @@ export default class SpotifySyncModel {
     }
 
     static async unlinkAccount() {
-        const { data } = await app.cores.api.customRequest( {
+        const { data } = await app.cores.api.customRequest({
             method: "POST",
             url: `/sync/spotify/unlink`,
         })
@@ -59,7 +59,7 @@ export default class SpotifySyncModel {
     }
 
     static async isAuthorized() {
-        const { data } = await app.cores.api.customRequest( {
+        const { data } = await app.cores.api.customRequest({
             method: "GET",
             url: `/sync/spotify/is_authorized`,
         })
@@ -68,7 +68,7 @@ export default class SpotifySyncModel {
     }
 
     static async getData() {
-        const { data } = await app.cores.api.customRequest( {
+        const { data } = await app.cores.api.customRequest({
             method: "GET",
             url: `/sync/spotify/data`,
         })
@@ -77,7 +77,7 @@ export default class SpotifySyncModel {
     }
 
     static async getCurrentPlaying() {
-        const { data } = await app.cores.api.customRequest( {
+        const { data } = await app.cores.api.customRequest({
             method: "GET",
             url: `/sync/spotify/currently_playing`,
         })
diff --git a/packages/comty.js/src/models/sync/services/tidal.js b/packages/comty.js/src/models/sync/services/tidal.js
new file mode 100644
index 00000000..39a3a46d
--- /dev/null
+++ b/packages/comty.js/src/models/sync/services/tidal.js
@@ -0,0 +1,83 @@
+import request from "../../../handlers/request"
+
+export default class TidalService {
+    static get api_instance() {
+        return globalThis.__comty_shared_state.instances["sync"]
+    }
+
+    static async linkAccount() {
+        if (!window) {
+            throw new Error("This method is only available in the browser.")
+        }
+
+        const { data } = await request({
+            instance: TidalService.api_instance,
+            method: "GET",
+            url: `/services/tidal/create_link`,
+        })
+
+        if (data.auth_url) {
+            window.open(data.auth_url, "_blank")
+        }
+
+        return data
+    }
+
+    static async unlinkAccount() {
+        if (!window) {
+            throw new Error("This method is only available in the browser.")
+        }
+
+        const { data } = await request({
+            instance: TidalService.api_instance,
+            method: "POST",
+            url: `/services/tidal/delete_link`,
+        })
+
+        return data
+    }
+
+    static async isActive() {
+        if (!window) {
+            throw new Error("This method is only available in the browser.")
+        }
+
+        const { data } = await request({
+            instance: TidalService.api_instance,
+            method: "GET",
+            url: `/services/tidal/is_active`,
+        })
+
+        return data
+    }
+
+    static async getCurrentUser() {
+        const { data } = await request({
+            instance: TidalService.api_instance,
+            method: "GET",
+            url: `/services/tidal/current`,
+        })
+
+        return data
+    }
+
+    static async getPlaybackUrl(track_id) {
+        const { data } = await request({
+            instance: TidalService.api_instance,
+            method: "GET",
+            url: `/services/tidal/playback/${track_id}`,
+        })
+
+        return data
+    }
+
+    static async getTrackManifest(track_id) {
+        const { data } = await request({
+            instance: TidalService.api_instance,
+            method: "GET",
+            url: `/services/tidal/manifest/${track_id}`,
+        })
+
+        return data
+    }
+}
\ No newline at end of file
diff --git a/packages/comty.js/src/remotes.js b/packages/comty.js/src/remotes.js
index 2807bf06..60d6c50e 100644
--- a/packages/comty.js/src/remotes.js
+++ b/packages/comty.js/src/remotes.js
@@ -24,6 +24,7 @@ const envOrigins = {
         marketplace: `http://${getCurrentHostname()}:3040`,
         music: `http://${getCurrentHostname()}:3050`,
         files: `http://${getCurrentHostname()}:3060`,
+        sync: `http://${getCurrentHostname()}:3070`,
     },
     "indev": {
         default: `https://indev_api.comty.app/main`,
@@ -32,6 +33,7 @@ const envOrigins = {
         marketplace: `https://indev_api.comty.app/marketplace`,
         music: `https://indev_api.comty.app/music`,
         files: `https://indev_api.comty.app/files`,
+        sync: `https://indev_api.comty.app/sync`,
     },
     "production": {
         default: "https://api.comty.app",
@@ -40,6 +42,7 @@ const envOrigins = {
         marketplace: `https://marketplace_api.comty.app`,
         music: `https://music_api.comty.app`,
         files: `https://files_api.comty.app`,
+        sync: `https://sync_api.comty.app`,
     }
 }
 
@@ -67,5 +70,9 @@ export default {
     files: {
         origin: composeRemote("files"),
         hasWebsocket: false,
+    },
+    sync: {
+        origin: composeRemote("sync"),
+        hasWebsocket: false,
     }
 }
\ No newline at end of file