Chapter 2 of 6
gethomepage Dashboard Card
PatchMon exposes a dedicated read-only endpoint designed to be consumed by a GetHomepage (formerly Homepage) customapi widget. Drop a PatchMon card into your existing homepage to see total hosts, pending updates, and security updates at a glance.
Related pages:
- Integration API Documentation: the generic scoped API (a different integration type)
- Users, Roles and RBAC: permission required to create the API key
At a glance
- Endpoint:
GET /api/v1/gethomepage/stats - Auth: HTTP Basic, using a PatchMon-issued API key dedicated to the GetHomepage integration
- Widget type:
customapiin GetHomepage - Fields available: 8 core metrics + a top-3 OS breakdown + a full
os_distributionarray - Rate limit: shares the standard API rate limit; GetHomepage polls every 60 seconds, well within the limit
Default widget
Out of the box the widget shows three metrics:
- Total Hosts
- Hosts Needing Updates
- Security Updates
Additional metrics can be added by editing the mappings: in your GetHomepage services.yml. See Configuration options below.
Prerequisites
- A running PatchMon 2.x instance reachable from the machine running GetHomepage.
- GetHomepage already installed and rendering at least one page.
- Network path between GetHomepage and PatchMon on HTTP or HTTPS. HTTPS is strongly recommended.
- PatchMon admin access (you need
can_manage_settingsto create API keys).
Setup
Step 1: Create a GetHomepage API key
- Sign in to PatchMon as an admin.
- Go to Settings → Integrations.
- Open the GetHomepage tab.
- Click New API Key and fill in:
- Token Name: e.g.
GetHomepage dashboard. - Allowed IP Addresses (optional): restrict to the IP of the machine running GetHomepage.
- Expiration Date (optional): set one if this is a temporary key.
- Token Name: e.g.
- Click Create Token.
Step 2: Copy the credentials
A success modal is shown with:
- Token Key: the API username.
- Token Secret: the API password. Shown only once. Save it immediately.
- Base64-encoded credentials: pre-built
Authorization: Basicvalue, ready to paste. - Complete widget configuration: a ready-to-drop-in YAML snippet.
Click Copy Config to copy the full YAML block. The secret is never retrievable again after you close this modal. If you lose it, you have to delete the key and create a new one.
Step 3: Configure GetHomepage
Option A: Paste the copied YAML (quickest)
- Open your GetHomepage
services.yml. - Paste the YAML block that PatchMon gave you.
- Save the file.
- Restart GetHomepage.
The YAML looks like this:
- PatchMon:
href: https://patchmon.example.com
description: PatchMon Statistics
icon: https://patchmon.example.com/assets/favicon.svg
widget:
type: customapi
url: https://patchmon.example.com/api/v1/gethomepage/stats
headers:
Authorization: Basic <base64_encoded_credentials>
mappings:
- field: total_hosts
label: Total Hosts
- field: hosts_needing_updates
label: Needs Updates
- field: security_updates
label: Security Updates
Option B: Build it by hand
-
Encode your credentials:
echo -n "YOUR_TOKEN_KEY:YOUR_TOKEN_SECRET" | base64 -
Paste the widget into
services.yml, replacing<your_base64_credentials>with the result:- PatchMon: href: https://patchmon.example.com description: PatchMon Statistics icon: https://patchmon.example.com/assets/favicon.svg widget: type: customapi url: https://patchmon.example.com/api/v1/gethomepage/stats headers: Authorization: Basic <your_base64_credentials> mappings: - field: total_hosts label: Total Hosts - field: hosts_needing_updates label: Needs Updates - field: security_updates label: Security Updates -
Restart GetHomepage:
docker restart gethomepage # or systemctl restart gethomepage
Configuration options
Customising the fields displayed
The default configuration displays 3 metrics. You can add more. PatchMon returns 8 numeric metrics and the top-3 OS breakdown, and the widget supports 6–8 comfortably before it becomes cluttered.
Each mappings entry has two parts:
field:the JSON key returned by the PatchMon API (case-sensitive, exactly as listed below)label:the human-readable label rendered by GetHomepage
Available fields
| Field | Type | Description | Included by default |
|---|---|---|---|
total_hosts |
Number | Total hosts in PatchMon, matching the Total Hosts card on the dashboard | Yes |
hosts_needing_updates |
Number | Hosts with at least one outdated package | Yes |
security_updates |
Number | Total security updates available across all hosts | Yes |
up_to_date_hosts |
Number | Hosts with zero outdated packages | No |
total_outdated_packages |
Number | Sum of all outdated packages across hosts | No |
hosts_with_security_updates |
Number | Hosts requiring at least one security patch | No |
total_repos |
Number | Active repositories being monitored | No |
recent_updates_24h |
Number | Successful updates in the last 24 hours | No |
top_os_1_name |
String | Name of the most common OS (e.g. "Ubuntu") | No (use label instead, see below) |
top_os_1_count |
Number | Count of the most common OS | No |
top_os_2_name |
String | Name of the 2nd most common OS | No |
top_os_2_count |
Number | Count of the 2nd most common OS | No |
top_os_3_name |
String | Name of the 3rd most common OS | No |
top_os_3_count |
Number | Count of the 3rd most common OS | No |
os_distribution |
Array | Full OS breakdown (advanced use only; GetHomepage cannot render arrays directly) | No |
last_updated |
String (ISO 8601) | Timestamp the stats were generated | No |
The
top_os_*_namestring fields render poorly incustomapiwidgets. Use the corresponding_countfields and put the OS name in thelabel:. See Displaying OS distribution.
Quick recipe: add a fourth metric
Before:
mappings:
- field: total_hosts
label: Total Hosts
- field: hosts_needing_updates
label: Needs Updates
- field: security_updates
label: Security Updates
After:
mappings:
- field: total_hosts
label: Total Hosts
- field: hosts_needing_updates
label: Needs Updates
- field: security_updates
label: Security Updates
- field: recent_updates_24h # newly added
label: Updated (24h)
Save, restart GetHomepage, and you've gone from 3 to 4 metrics.
Example widget configurations
All examples assume you've already populated the Authorization header with your encoded credentials.
Security-focused widget
widget:
type: customapi
url: https://patchmon.example.com/api/v1/gethomepage/stats
headers:
Authorization: Basic <credentials>
mappings:
- field: security_updates
label: Security Patches
- field: hosts_with_security_updates
label: Hosts at Risk
- field: hosts_needing_updates
label: Total Pending
Repository / coverage widget
widget:
type: customapi
url: https://patchmon.example.com/api/v1/gethomepage/stats
headers:
Authorization: Basic <credentials>
mappings:
- field: total_repos
label: Repositories
- field: total_hosts
label: Managed Hosts
- field: up_to_date_hosts
label: Up-to-Date
Activity widget
widget:
type: customapi
url: https://patchmon.example.com/api/v1/gethomepage/stats
headers:
Authorization: Basic <credentials>
mappings:
- field: recent_updates_24h
label: Updated (24h)
- field: hosts_needing_updates
label: Pending Updates
- field: up_to_date_hosts
label: Fully Patched
Maximum-information widget (all 8 numeric metrics)
widget:
type: customapi
url: https://patchmon.example.com/api/v1/gethomepage/stats
headers:
Authorization: Basic <credentials>
mappings:
- field: total_hosts
label: Total Hosts
- field: hosts_needing_updates
label: Needs Updates
- field: up_to_date_hosts
label: Up-to-Date
- field: security_updates
label: Security Updates
- field: hosts_with_security_updates
label: Security Hosts
- field: total_outdated_packages
label: Outdated Packages
- field: total_repos
label: Repositories
- field: recent_updates_24h
label: Updated (24h)
Note this widget will be quite tall. Keep it to 3–5 metrics for most layouts.
Multiple environments
# Production - security-focused
- PatchMon Prod:
href: https://patchmon-prod.example.com
description: Production Patches
icon: https://patchmon-prod.example.com/assets/favicon.svg
widget:
type: customapi
url: https://patchmon-prod.example.com/api/v1/gethomepage/stats
headers:
Authorization: Basic <prod_credentials>
mappings:
- field: total_hosts
label: Hosts
- field: security_updates
label: Security
- field: hosts_needing_updates
label: Pending
# Development - package-focused
- PatchMon Dev:
href: https://patchmon-dev.example.com
description: Development Patches
icon: https://patchmon-dev.example.com/assets/favicon.svg
widget:
type: customapi
url: https://patchmon-dev.example.com/api/v1/gethomepage/stats
headers:
Authorization: Basic <dev_credentials>
mappings:
- field: total_hosts
label: Hosts
- field: total_outdated_packages
label: Packages
- field: up_to_date_hosts
label: Updated
Displaying OS distribution
Step 1: Find out your top 3 operating systems
curl -s -H "Authorization: Basic YOUR_BASE64_CREDENTIALS" \
https://patchmon.example.com/api/v1/gethomepage/stats \
| jq '{top_os_1_name, top_os_1_count, top_os_2_name, top_os_2_count, top_os_3_name, top_os_3_count}'
Sample output:
{
"top_os_1_name": "Ubuntu",
"top_os_1_count": 35,
"top_os_2_name": "Debian",
"top_os_2_count": 18,
"top_os_3_name": "Rocky Linux",
"top_os_3_count": 12
}
Step 2: Add the counts to the widget, using the names as labels
mappings:
- field: total_hosts
label: Total Hosts
- field: top_os_1_count
label: Ubuntu # from top_os_1_name
- field: top_os_2_count
label: Debian # from top_os_2_name
- field: top_os_3_count
label: Rocky Linux # from top_os_3_name
Step 3: Restart GetHomepage
docker restart gethomepage
# or
systemctl restart gethomepage
The widget now shows your infrastructure OS breakdown. If your top 3 OSes change over time, update the labels; PatchMon will reorder the counts automatically based on actual host counts.
Custom icon
# PatchMon logo
icon: https://patchmon.example.com/assets/favicon.svg
icon: https://patchmon.example.com/assets/logo_dark.png
icon: https://patchmon.example.com/assets/logo_light.png
# GetHomepage built-in icon
icon: server
# Local icon inside your GetHomepage image / volume
icon: /icons/patchmon.png
API reference
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/gethomepage/stats |
Returns the widget payload described above |
GET |
/api/v1/gethomepage/health |
Simple liveness probe. Returns status: "ok", the current timestamp, and the name of the API key used. |
Authentication
- Type: HTTP Basic Authentication
- Format:
Authorization: Basic <base64(token_key:token_secret)> - Token type:
gethomepage(enforced server-side; a credential created under the API tab won't work here, and vice versa)
Stats response
{
"total_hosts": 42,
"total_outdated_packages": 156,
"total_repos": 12,
"hosts_needing_updates": 15,
"up_to_date_hosts": 27,
"security_updates": 23,
"hosts_with_security_updates": 8,
"recent_updates_24h": 34,
"os_distribution": [
{ "name": "Ubuntu", "count": 20, "os_type": "linux", "os_version": "22.04" },
{ "name": "Debian", "count": 12, "os_type": "linux", "os_version": "12" },
{ "name": "Rocky Linux", "count": 10, "os_type": "linux", "os_version": "9" }
],
"top_os_1_name": "Ubuntu",
"top_os_1_count": 20,
"top_os_2_name": "Debian",
"top_os_2_count": 12,
"top_os_3_name": "Rocky Linux",
"top_os_3_count": 10,
"last_updated": "2026-04-24T12:34:56Z"
}
Health response
{
"status": "ok",
"timestamp": "2026-04-24T12:34:56Z",
"api_key": "GetHomepage dashboard"
}
Managing API keys
Viewing existing keys
Go to Settings → Integrations → GetHomepage. For each key you see:
- Token name
- Creation date
- Last-used timestamp
- Active / Inactive status
- Expiration date (if set)
Disable / Enable / Delete
- Disable / Enable: toggle the button on the row to temporarily block or restore access without deleting the credential.
- Delete: click the trash icon. This is permanent; any widget using that key will start returning 401.
Security features
- IP restrictions: per-key allowlist (CIDRs supported).
- Expiration dates: automatic sunset.
- Last-used tracking: spot keys that have silently stopped working, or suspicious usage.
- One-time secret display: the secret is shown once, at creation. Never again.
Troubleshooting
Error: "Missing or invalid authorization header"
GetHomepage is not sending the Authorization header correctly.
- Verify the
headers:section is properly indented inservices.yml. - Re-encode the credentials; make sure you used
-nwithechoso no trailing newline ends up in the base64. - Confirm you're using
type: customapi, as other widget types ignore arbitrary headers.
Error: "Invalid API key"
The key does not exist in PatchMon.
- Check Settings → Integrations → GetHomepage for the key.
- Re-create the key if it's missing, update the GetHomepage config with the new credentials.
Error: "API key is disabled" / "API key has expired"
Enable the key, or create a new one with a later expiration.
Error: "IP address not allowed"
Your GetHomepage instance's outbound IP is not in the credential's allowlist. Either add it, or remove the allowlist if not needed.
Widget shows nothing
Work through this checklist:
- Can GetHomepage reach PatchMon at all? Test with
curlfrom inside the GetHomepage container:curl -v https://patchmon.example.com/api/v1/gethomepage/health -H "Authorization: Basic ..." - Is the API key active and not expired?
- Is the base64 credential correct?
- Is
services.ymlvalid YAML? (runyamllint services.ymlif unsure) - Has GetHomepage been restarted since the last change?
- Check GetHomepage's container logs for error messages.
Testing the endpoint directly
# Step 1: encode
echo -n "your_key:your_secret" | base64
# Step 2: test
curl -H "Authorization: Basic YOUR_BASE64" \
https://patchmon.example.com/api/v1/gethomepage/stats | jq
Every numeric field in the response (including top_os_*_count) can be used in a widget mapping.
Security best practices
- Always use HTTPS. The credentials are sent on every 60-second poll. Don't put them on the wire in the clear.
- IP-restrict the key to the GetHomepage instance's IP.
- Give the key an expiration and rotate it as part of your normal credential rotation.
- Monitor the last-used timestamp to spot suspicious activity.
- One key per GetHomepage instance if you're running several, to make rotation and revocation easier.
- Store
services.ymlwith appropriate file permissions on the GetHomepage host.
Integration architecture
┌──────────────────┐
│ GetHomepage │
│ Dashboard │
└────────┬─────────┘
│
│ HTTP(S) GET, every 60s
│ Authorization: Basic <base64>
│
▼
┌──────────────────┐
│ PatchMon │
│ API server │
│ │
│ /api/v1/ │
│ gethomepage/ │
│ stats │
└────────┬─────────┘
│
│ Aggregate query
│
▼
┌──────────────────┐
│ PostgreSQL │
│ │
│ - Hosts │
│ - Packages │
│ - Updates │
│ - Repositories │
└──────────────────┘
Rate limiting
The /api/v1/gethomepage/* endpoints are subject to PatchMon's general API rate limit of 100 requests per 15 minutes per IP by default. GetHomepage's default poll interval of 60 seconds sits well within this limit (15 requests per 15 minutes). If you lower GetHomepage's poll interval aggressively, you may start hitting 429 Too Many Requests; stay above 10 seconds.
Support and resources
- PatchMon documentation: patchmon.net/docs
- GetHomepage documentation: gethomepage.dev
- PatchMon Discord: patchmon.net/discord
- GitHub issues: github.com/PatchMon/PatchMon/issues