Skip to main content

Overview

The Apps API manages applications displayed on Homarr boards. Apps represent external services, websites, or tools that users want to access from their dashboard.

Queries

all

Get all applications.
const apps = await api.app.all.query();
Authentication: Protected Response: Array of apps ordered by name
id
string
App unique identifier
name
string
App name (1-64 characters)
description
string | null
App description (max 512 characters)
iconUrl
string
URL to app icon
href
string | null
App URL (must be valid URL or null)
pingUrl
string | null
URL to ping for status checks

getPaginated

Get apps with pagination.
const result = await api.app.getPaginated.query({
  page: 1,
  pageSize: 20,
  search: "media",
});
Parameters:
page
number
required
Page number (1-indexed)
pageSize
number
required
Number of items per page
Optional search query to filter by name
Response:
items
array
Array of app objects
totalCount
number
Total number of apps matching the search

Search apps by name.
const apps = await api.app.search.query({
  query: "plex",
  limit: 10,
});
Parameters:
query
string
required
Search query string
limit
number
default:10
Maximum results (1-100)

selectable

Get apps suitable for selection in UI (minimal data).
const apps = await api.app.selectable.query();
Returns: Apps with only id, name, iconUrl, href, pingUrl, and description

byId

Get a single app by ID.
const app = await api.app.byId.query({ id: "app-id" });
Authentication: Public Throws: NOT_FOUND if app doesn’t exist

byIds

Get multiple apps by IDs.
const apps = await api.app.byIds.query(["app-id-1", "app-id-2"]);
Authentication: Public

Mutations

create

Create a new application.
const result = await api.app.create.mutate({
  name: "Plex",
  description: "Media server",
  iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/svg/plex.svg",
  href: "https://plex.example.com",
  pingUrl: "https://plex.example.com/api/v2",
});
Permission Required: app-create Parameters:
name
string
required
App name (1-64 characters, trimmed)
description
string | null
App description (max 512 characters)
iconUrl
string
required
URL to app icon (must be non-empty)
href
string | null
App URL - must be valid URL format, cannot use javascript: protocol
pingUrl
string | null
URL for status checks (must be HTTP/HTTPS)
Response:
appId
string
ID of the newly created app
...
object
All app properties
Validation:
  • href must be a valid URL or empty string (converted to null)
  • pingUrl must use HTTP or HTTPS protocol
  • javascript: URLs are blocked for security

createMany

Create multiple applications at once.
await api.app.createMany.mutate([
  {
    name: "Plex",
    description: "Media server",
    iconUrl: null, // Will auto-fetch icon
    href: "https://plex.example.com",
  },
  {
    name: "Sonarr",
    description: "TV show management",
    iconUrl: null,
    href: "https://sonarr.example.com",
  },
]);
Permission Required: app-create Notes:
  • If iconUrl is null, Homarr will attempt to auto-fetch an icon based on the app name
  • Falls back to default Homarr icon if no icon is found
  • Must provide at least one app

update

Update an existing application.
await api.app.update.mutate({
  id: "app-id",
  name: "Plex Media Server",
  description: "Updated description",
  iconUrl: "https://new-icon-url.com/icon.svg",
  href: "https://new-url.example.com",
  pingUrl: "https://new-url.example.com/api",
});
Permission Required: app-modify-all Throws: NOT_FOUND if app doesn’t exist

delete

Delete an application.
await api.app.delete.mutate({ id: "app-id" });
Permission Required: app-full-all
Deleting an app will remove it from all boards that reference it.

OpenAPI Endpoints

Some app endpoints are also exposed via REST API:

GET /api/apps

List all applications.
curl -X GET https://your-homarr.com/api/apps \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /api/apps/paginated

Get paginated apps.
curl -X GET "https://your-homarr.com/api/apps/paginated?page=1&pageSize=20" \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /api/apps/search

Search apps.
curl -X GET "https://your-homarr.com/api/apps/search?query=plex&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /api/apps/selectable

Get selectable apps (minimal data).
curl -X GET https://your-homarr.com/api/apps/selectable \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /api/apps/

Get app by ID.
curl -X GET https://your-homarr.com/api/apps/app-id-123 \
  -H "Authorization: Bearer YOUR_API_KEY"

POST /api/apps

Create a new app.
curl -X POST https://your-homarr.com/api/apps \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Plex",
    "description": "Media server",
    "iconUrl": "https://icon-url.com/plex.svg",
    "href": "https://plex.example.com",
    "pingUrl": "https://plex.example.com/api"
  }'

PATCH /api/apps/

Update an app.
curl -X PATCH https://your-homarr.com/api/apps/app-id-123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "app-id-123",
    "name": "Updated Name",
    "description": "Updated description",
    "iconUrl": "https://new-icon.com/icon.svg",
    "href": "https://new-url.com",
    "pingUrl": "https://new-url.com/api"
  }'

DELETE /api/apps/

Delete an app.
curl -X DELETE https://your-homarr.com/api/apps/app-id-123 \
  -H "Authorization: Bearer YOUR_API_KEY"

Examples

Bulk Import Apps

const appsToCreate = [
  { name: "Plex", href: "https://plex.example.com", description: "Media Server" },
  { name: "Sonarr", href: "https://sonarr.example.com", description: "TV Shows" },
  { name: "Radarr", href: "https://radarr.example.com", description: "Movies" },
];

await api.app.createMany.mutate(
  appsToCreate.map(app => ({
    ...app,
    iconUrl: null, // Auto-fetch icons
  }))
);

Search and Update

// Find apps matching a pattern
const mediaApps = await api.app.search.query({
  query: "media",
  limit: 50,
});

// Update all matching apps
for (const app of mediaApps) {
  await api.app.update.mutate({
    ...app,
    description: `${app.description} (Media Service)`,
  });
}

Get App with Error Handling

try {
  const app = await api.app.byId.query({ id: "app-id" });
  console.log(`App: ${app.name}`);
} catch (error) {
  if (error.code === 'NOT_FOUND') {
    console.log('App does not exist');
  } else {
    console.error('Unexpected error:', error);
  }
}

Build docs developers (and LLMs) love