diff --git a/src/preload/index.ts b/src/preload/index.ts
index 83dc12d1..a4b8a061 100644
--- a/src/preload/index.ts
+++ b/src/preload/index.ts
@@ -1,4 +1,5 @@
 import { NotificationConstructorOptions, contextBridge, ipcRenderer } from 'electron'
+import os from 'os'
 import { electronAPI } from '@electron-toolkit/preload'
 import { IPC_EVENTS } from '@shared/constants'
 import {
@@ -12,6 +13,8 @@ export interface IElectronAPI {
   env: NodeJS.ProcessEnv,
   appVersion: string,
   platform: string,
+  osRelease: string,
+  arch: string,
 
   // Use `contextBridge` APIs to expose Electron APIs to
   // renderer only if context isolation is enabled, otherwise
@@ -88,6 +91,8 @@ const api: IElectronAPI = {
   env: process.env,
   appVersion: process.env['APP_VERSION'] || '0.0.1',
   platform: process.platform,
+  osRelease: os.release(),
+  arch: process.arch,
   i18nextElectronBackend: preloadBindings(ipcRenderer, process),
   //SYNC EMITTERS - expect response
   login: setEmitterSync<Account | undefined>(IPC_EVENTS.LOGIN),
diff --git a/src/shared/useNethVoiceAPI.ts b/src/shared/useNethVoiceAPI.ts
index 7b94c99f..42d204ba 100644
--- a/src/shared/useNethVoiceAPI.ts
+++ b/src/shared/useNethVoiceAPI.ts
@@ -24,6 +24,29 @@ import { requires2FA } from '@shared/utils/jwt'
 const PRIMARY_API_BASE_PATH = '/api'
 const FALLBACK_API_BASE_PATH = '/webrest'
 
+function getNethlinkClientInfo(): {
+  nethlink_version: string
+  os_type: string
+  os_release: string
+  arch: string
+} {
+  const api = typeof window !== 'undefined' ? (window as any).api : undefined
+  if (api) {
+    return {
+      nethlink_version: api.appVersion || '',
+      os_type: api.platform || '',
+      os_release: api.osRelease || '',
+      arch: api.arch || ''
+    }
+  }
+  return {
+    nethlink_version: (typeof process !== 'undefined' && process.env?.['APP_VERSION']) || '',
+    os_type: typeof process !== 'undefined' ? process.platform : '',
+    os_release: '',
+    arch: typeof process !== 'undefined' ? process.arch : ''
+  }
+}
+
 export const useNethVoiceAPI = (loggedAccount: Account | undefined = undefined) => {
   const { GET, POST, DELETE } = useNetwork()
   let isFirstHeartbeat = true
@@ -161,6 +184,9 @@ export const useNethVoiceAPI = (loggedAccount: Account | undefined = undefined)
     if (currentApiBasePath !== PRIMARY_API_BASE_PATH) {
       return false
     }
+    if (path.includes('/user/nethlink')) {
+      return false
+    }
 
     // Try fallback for connection errors (404, 503, or network failures)
     const isConnectionError = error?.response?.status === 404 || error?.response?.status === 503 || !error?.response
@@ -586,15 +612,20 @@ export const useNethVoiceAPI = (loggedAccount: Account | undefined = undefined)
       //the !loggedAccount flag allow to reduce the invocation only to the backend module and only at the first login
       if (ext && !loggedAccount && isFirstHeartbeat) {
         isFirstHeartbeat = false
-        const response = await User.heartbeat(ext.id, data.username)
-        Log.debug('Sent HEARTBEAT', { response })
+        try {
+          const response = await User.heartbeat(ext.id, data.username)
+          Log.debug('Sent HEARTBEAT', { response })
+        } catch (error) {
+          Log.debug('HEARTBEAT skipped: endpoint unavailable', { error })
+        }
       }
       return data
     },
     all: async () => await _GET(buildApiPath('/user/all')),
     all_avatars: async () => await _GET(buildApiPath('/user/all_avatars')),
     all_endpoints: async () => await _GET(buildApiPath('/user/endpoints/all')),
-    heartbeat: async (extension: string, username: string) => await _POST(buildApiPath('/user/nethlink'), { extension, username }),
+    heartbeat: async (extension: string, username: string) =>
+      await _POST(buildApiPath('/user/nethlink'), { extension, username, ...getNethlinkClientInfo() }),
     settings: async (settings: Partial<AccountData['settings']>) =>
       await _POST(buildApiPath('/user/settings'), settings),
     default_device: async (deviceIdInformation: Extension, force = false): Promise<boolean> => {
