API: sites and clients
List and filter sites, read a site's plugins and themes, add sites, refresh inventory.
Updated Oct 11, 2026
List sites
GET /sites
Ability: read. Optional filters:
client_id |
Only this client’s sites |
|---|---|
status |
connected, pending, disconnected |
search |
Part of the name or URL |
plugin |
Sites with a plugin whose name or slug contains this |
plugin_below |
With plugin: only where it’s older than this version |
has_updates |
1 for sites with updates waiting |
# Which sites run Gravity Forms older than 3.0?
curl "https://app.wpforeman.com/api/v1/sites?plugin=gravityforms&plugin_below=3.0" \
-H "Authorization: Bearer YOUR_TOKEN"
{
"data": [{
"id": 12, "name": "Shop", "url": "https://shop.example", "status": "connected",
"client": { "id": 3, "name": "Acme" },
"wordpress_version": "6.9.1", "php_version": "8.3.14", "plugin_version": "0.5.0",
"updates_available": 2, "last_seen_at": "2026-10-04T13:02:11+00:00",
"inventory_checked_at": "2026-10-04T13:02:11+00:00", "last_error": null
}]
}
Get one site
GET /sites/{id}
Ability: read. Adds core, plugins, themes (each with version, active, update_available, new_version), last_backup and backup_storage_bytes (what this site’s backups take up in storage).
Add a site
POST /sites
Ability: sites. Body: name, url, optional client_id. The response includes a one-time connection_key (valid 24 hours) and the plugin download URL. Paste the key into Settings › WP Foreman on the site. Answers 403 if your account is at its site limit.
DELETE /sites/{id}
Ability: sites. Removes the site. Its backups are kept for 30 days (it can be brought back from the Sites page until then), then deleted. Answers 409 while a backup, restore or update is running. See Disconnecting a site.
Refresh inventory
POST /sites/{id}/refresh
POST /sites/refresh
Ability: sites. Checks one site, or every connected site at once. The all-sites version returns [{ site_id, ok, error }].
Clients
GET /clients
POST /clients
PATCH /clients/{id}
Reading needs read; creating and updating need sites. Fields: name (required to create), contact_name, phone, website, report_emails (array), brand_color (#rrggbb), notes. PATCH changes only the fields you send. Logos are uploaded in the app. To move a site to a client, send client_id when adding the site, or change it in the app.
Activity log
GET /sites/{id}/activity
GET /activity/{id}
Ability: read. Every plugin, theme and core change, with summary lines like "Yoast SEO 26.1 → 26.2".
Site log
GET /log
GET /sites/{id}/log
Ability: read. The site log, newest first (see The site log). Optional filters: category (backups, restores, changes, detected, connection, access, users, rules, uptime, performance, reports, security, visual; repeat as category[] for several), type (one entry type such as wp.plugins.install; repeat as type[]), level (info, success, warning, error), q (text search), range (today, 7d, 30d, this_month, last_month), from and to (YYYY-MM-DD, in your timezone), and on /log only site (site id). Paginated with page and per_page.
Each entry: id, site_id, site_name, category, type (for example backup.succeeded, plugins.update, site.change_detected, admin.login), level, title, details (object; varies by type), actor_type (user, foreman, api, schedule, rule, site, site_user, support, system), actor_label, occurred_at.
curl -H "Authorization: Bearer wpf_…" \
"https://app.wpforeman.com/api/v1/sites/12/log?level[]=warning&level[]=error&from=2026-10-01"
Notes
GET /sites/{id}/notes
POST /sites/{id}/notes
PATCH /sites/{id}/notes/{note}
DELETE /sites/{id}/notes/{note}
Abilities: read to list, sites to add, change and delete. Body: body (text, up to 10,000 characters) and pinned (true/false). Each note: id, body, pinned, by, created_at, updated_at; pinned first. See Site overview, notes and settings.
Performance
GET /sites/{id}/performance
Ability: read. Latest PageSpeed result for mobile and desktop: score (0–100), lcp_ms, tbt_ms, cls, fcp_ms, si_ms, ttfb_ms, field (real-visitor Core Web Vitals when Google has them, each with value and rating), opportunities, checked_at; plus history (90 days of scores). See Site speed.
GET /sites/{id}/visual
Ability: read. Visual checks: pages (each path and label), threshold (percent changed that gets flagged), and the last 10 checks, each with status (queued, running, done, changed, failed), changed (screenshots over the threshold) and shots (path, device desktop|mobile, diff_pct, error). See Visual checks.
POST /sites/{id}/visual/check
Ability: sites. Starts a check now. Answers 202 with the check’s id, or 409 if one is already running.
Uptime
GET /sites/{id}/uptime
Ability: read. Current status (up, down, blocked, unknown), uptime percentages for 24h, 7d and 30d, the last 20 incidents (each with reason, regions, started_at, ended_at, seconds), ssl.expires_at, domain.expires_at, and a series of checks. Optional range: 24h (every check), 7d or 30d (hourly). See How uptime monitoring works.
Site traffic
GET /sites/{id}/analytics
Ability: read. Traffic from the site’s Google Analytics, Plausible or Umami (see Connect Plausible or Umami). Optional range: 7d, 30d (default), 90d. Answers 409 if analytics isn’t set up for the site, 502 if the analytics service refused.
{ "data": {
"provider": "plausible", "range": "30d", "from": "2026-09-08", "to": "2026-10-07",
"totals": { "visitors": 1840, "visits": 2310, "pageviews": 5120, "bounce_rate": 48, "avg_duration": 74 },
"previous": { "visitors": 1610, "visits": 2050, "pageviews": 4700, "bounce_rate": 52, "avg_duration": 69 },
"series": [ { "date": "2026-09-08", "visitors": 61, "pageviews": 170 } ],
"pages": [ { "name": "/", "visitors": 900, "pageviews": 1300 } ],
"sources": [ { "name": "Google", "visitors": 700 } ],
"fetched_at": "2026-10-07T14:02:11+00:00"
} }
avg_duration is in seconds, bounce_rate a percentage. For Umami, pages[].pageviews is null and visitors holds pageviews.
While you were away
GET /digest
Ability: read. The crew report described in While you were away, for any period. Optional since and until (ISO 8601; default the last 24 hours, at most 31 days back). Handy for posting a morning summary to Slack or your own dashboard.
{ "data": {
"since_label": "since yesterday 7:00 AM",
"headline": "The crew backed up 14 sites and applied 9 updates. 1 thing needs you. 2 things are ready for your OK.",
"needs_you": [ { "kind": "backup", "level": "error", "site_id": 3, "site": "Acme Plumbing", "text": "Last backup failed: …", "href": "/sites/3/backups" } ],
"ready": [ { "kind": "core", "site_id": 3, "site": "Acme Plumbing", "text": "WordPress 6.8.1 → 6.8.2 (security and bug fixes)",
"action": "update", "picks": [ { "site_id": 3, "type": "core", "slug": "core" } ], "href": "/sites/3/plugins" } ],
"crew": [ { "key": "lockup", "name": "Lockup", "role": "Backups", "lines": ["Backed up 14 sites, all good."], "count": 14, "ok": true } ],
"good_to_know": [ { "site_id": null, "site": null, "text": "Your rules will take care of 6 more updates: Patch Tuesday (Tue 2:00 AM).", "href": "/rules" } ],
"quiet": false
} }
To approve a ready item, send its picks to POST /updates (ability plugins); see API: plugins, themes and updates. href paths are relative to https://app.wpforeman.com.
Security
GET /sites/{id}/security
Ability: read. Open known vulnerabilities (worst first) with name, type, installed_version, fixed_in, severity, cvss_score, title, cve, link; counts by severity; issues fixed in the last 90 days; and when the vulnerability list was last updated. See Known vulnerabilities.
Client reports
GET /sites/{id}/reports
Ability: read. The site’s reports, newest first: { id, label, from, to, highlights, public_url, created_at, sent_at, sent_to }.
POST /sites/{id}/reports
Ability: sites. Send preset (last_month, this_month, last_7, last_30, last_quarter) or from and to (YYYY-MM-DD, inclusive, in your timezone). Optional sections: any of attention, updates, uptime, backups, speed, traffic, worklog, health, visual (saved as the site’s default; left out = the site’s saved choice). Answers 201 with the report, including report: the full snapshot (highlights, updates, backups, uptime, performance, traffic, health). See Client reports.
curl -X POST https://app.wpforeman.com/api/v1/sites/12/reports \
-H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
-d '{"from":"2026-09-01","to":"2026-09-30"}'
GET /reports/{id}
Ability: read. One report with its snapshot.
DELETE /reports/{id}
Ability: sites. Deletes it and turns off its client link.
POST /reports/{id}/send
Ability: sites. Emails the report: to (array of up to 10 addresses), optional note, optional remember (default true: saves the addresses on the site’s client). Answers { sent_to, sent_at }.
Thanks. If something was missing, tell us what.