Skip to main content

Overview

The Widgets API provides access to real-time data for various widget types. Each widget category has its own sub-router with specific queries and subscriptions.

Widget Categories

Homarr supports the following widget routers:
RouterPurpose
appApplication widget data
weatherWeather data and forecasts
calendarCalendar events
dnsHoleDNS hole statistics (Pi-hole, AdGuard)
smartHomeSmart home device control
mediaServerMedia server statistics (Plex, Jellyfin)
mediaRequestsMedia request systems (Overseerr, Jellyseerr)
mediaReleaseUpcoming media releases
mediaTranscodingTranscoding status (Tdarr)
downloadsDownload client stats (qBittorrent, etc.)
indexerManagerIndexer manager stats (Prowlarr)
healthMonitoringSystem health monitoring (Healthchecks)
notebookNotebook widget content
rssFeedRSS feed reader
stockPriceStock price data
coolifyCoolify deployment status
minecraftMinecraft server status
networkControllerNetwork controller stats (UniFi)
firewallFirewall statistics (OPNsense, pfSense)
notificationsNotification system data
releasesSoftware release tracking
optionsWidget configuration options

Weather Widget

atLocation

Get current weather for a location.
const weather = await api.widget.weather.atLocation.query({
  latitude: 40.7128,
  longitude: -74.0060,
});
Parameters:
latitude
number
required
Latitude coordinate
longitude
number
required
Longitude coordinate
Authentication: Public Response:
current
object
Current weather conditions
temperature
number
Temperature in configured units
condition
string
Weather condition description
humidity
number
Humidity percentage
windSpeed
number
Wind speed
forecast
array
Forecast for upcoming days

subscribeAtLocation

Subscribe to real-time weather updates.
const subscription = api.widget.weather.subscribeAtLocation.subscribe(
  {
    latitude: 40.7128,
    longitude: -74.0060,
  },
  {
    onData: (weather) => {
      console.log('Weather updated:', weather);
    },
    onError: (error) => {
      console.error('Weather subscription error:', error);
    },
  }
);

// Unsubscribe when done
subscription.unsubscribe();

Media Server Widget

getStats

Get media server statistics.
const stats = await api.widget.mediaServer.getStats.query({
  integrationId: "integration-id",
});
Parameters:
integrationId
string
required
ID of the media server integration
Authentication: Protected (requires integration access) Response:
streams
number
Current active streams
libraries
array
Library statistics
recentlyAdded
array
Recently added media items

DNS Hole Widget

getStatistics

Get DNS blocking statistics.
const stats = await api.widget.dnsHole.getStatistics.query({
  integrationId: "integration-id",
});
Response:
queriesTotal
number
Total queries
queriesBlocked
number
Blocked queries
percentBlocked
number
Percentage blocked
topQueries
array
Most frequent queries
topBlocked
array
Most blocked domains

Smart Home Widget

getDevices

Get smart home device status.
const devices = await api.widget.smartHome.getDevices.query({
  integrationId: "integration-id",
});
Response:
id
string
Device ID
name
string
Device name
type
string
Device type (light, switch, sensor, etc.)
state
object
Current device state

controlDevice

Control a smart home device.
await api.widget.smartHome.controlDevice.mutate({
  integrationId: "integration-id",
  deviceId: "device-id",
  action: "turn_on",
  parameters: {
    brightness: 80,
  },
});
Parameters:
integrationId
string
required
Integration ID
deviceId
string
required
Device ID to control
action
string
required
Action to perform (turn_on, turn_off, toggle, etc.)
parameters
object
Action-specific parameters
Permission Required: Integration interact access

Calendar Widget

getEvents

Get calendar events.
const events = await api.widget.calendar.getEvents.query({
  integrationIds: ["integration-id-1", "integration-id-2"],
  start: new Date(),
  end: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
});
Parameters:
integrationIds
string[]
required
Array of calendar integration IDs
start
Date
required
Start date for event range
end
Date
required
End date for event range
Response:
id
string
Event ID
title
string
Event title
start
Date
Event start time
end
Date
Event end time
allDay
boolean
Whether the event is all-day
calendarId
string
Source calendar ID

Downloads Widget

getQueue

Get download queue status.
const queue = await api.widget.downloads.getQueue.query({
  integrationId: "integration-id",
});
Response:
active
number
Active downloads
paused
number
Paused downloads
completed
number
Completed downloads
downloadSpeed
number
Current download speed (bytes/sec)
uploadSpeed
number
Current upload speed (bytes/sec)
items
array
Download queue items

controlDownload

Control download operations.
await api.widget.downloads.controlDownload.mutate({
  integrationId: "integration-id",
  action: "pause",
  hash: "download-hash",
});
Actions: pause, resume, delete, force_start Permission Required: Integration interact access

Notebook Widget

getContent

Get notebook content.
const content = await api.widget.notebook.getContent.query({
  itemId: "item-id",
});
Response:
content
string
Markdown content

saveContent

Save notebook content.
await api.widget.notebook.saveContent.mutate({
  itemId: "item-id",
  content: "# My Notes\n\nThis is my notebook content.",
});
Parameters:
itemId
string
required
Notebook item ID
content
string
required
Markdown content to save

RSS Feed Widget

getFeed

Get RSS feed entries.
const feed = await api.widget.rssFeed.getFeed.query({
  url: "https://example.com/feed.xml",
  limit: 10,
});
Parameters:
url
string
required
RSS feed URL
limit
number
default:10
Maximum entries to return
Authentication: Public Response:
title
string
Feed title
items
array
Feed entries
title
string
Entry title
Entry URL
published
Date
Publication date
description
string
Entry description/summary

Stock Price Widget

getPrice

Get current stock price.
const price = await api.widget.stockPrice.getPrice.query({
  symbol: "AAPL",
});
Parameters:
symbol
string
required
Stock ticker symbol
Response:
symbol
string
Stock symbol
price
number
Current price
change
number
Price change
changePercent
number
Percentage change

Widget Options

getAvailableOptions

Get available configuration options for a widget kind.
const options = await api.widget.options.getAvailableOptions.query({
  kind: "weather",
});
Returns: Schema describing available widget options

Common Patterns

Widget Data Caching

Widget data is automatically cached to prevent excessive API calls:
// First call fetches from source
const data1 = await api.widget.weather.atLocation.query({ ... });

// Subsequent calls within cache window return cached data
const data2 = await api.widget.weather.atLocation.query({ ... });

Error Handling

try {
  const data = await api.widget.mediaServer.getStats.query({
    integrationId: "integration-id",
  });
} catch (error) {
  if (error.code === 'NOT_FOUND') {
    console.error('Integration not found');
  } else if (error.code === 'FORBIDDEN') {
    console.error('No access to this integration');
  }
}

Real-time Subscriptions

// Subscribe to weather updates
const unsubscribe = api.widget.weather.subscribeAtLocation.subscribe(
  { latitude: 40.7128, longitude: -74.0060 },
  {
    onData: (weather) => {
      updateUI(weather);
    },
    onError: (error) => {
      console.error('Subscription error:', error);
    },
  }
);

// Clean up on unmount
onCleanup(() => unsubscribe());

Build docs developers (and LLMs) love