Content Guard Pro provides a REST API for programmatic access to findings and scan functionality. Use it for custom integrations, monitoring dashboards, or automation.
Authentication #
WordPress Nonce (Logged-in Users) #
For requests from WordPress admin:
fetch('/wp-json/content-guard-pro/v1/findings', {
headers: {
'X-WP-Nonce': wpApiSettings.nonce
}
});
Application Passwords #
For external applications (WordPress 5.6+):
1. Go to Users → Your Profile
2. Scroll to Application Passwords
3. Create new password for your app
4. Use Basic Auth: username:application_password
curl -u "admin:xxxx xxxx xxxx xxxx"
https://yoursite.com/wp-json/content-guard-pro/v1/findings
Endpoints #
List Findings #
GET /wp-json/content-guard-pro/v1/findings
Parameters:
| Parameter | Type | Description |
| ———– | —— | ————- |
status |
string | Filter by status (open, quarantined, ignored, resolved) |
severity |
string | Filter by severity (critical, suspicious, review) |
object_type |
string | Filter by type (post, postmeta, option) |
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 50, max: 100) |
Example Request:
GET /wp-json/content-guard-pro/v1/findings?status=open&severity=critical&per_page=10
Example Response:
{
"findings": [
{
"id": 123,
"fingerprint": "abc123...",
"object_type": "post",
"object_id": 456,
"field": "post_content",
"rule_id": "ext_script_non_allowlist",
"severity": "critical",
"confidence": 90,
"matched_excerpt": "[external script tag detected]",
"first_seen": "2025-01-15T10:30:00Z",
"last_seen": "2025-01-15T10:30:00Z",
"status": "open"
}
],
"total": 15,
"pages": 2,
"page": 1
}
Get Single Finding #
GET /wp-json/content-guard-pro/v1/findings/{id}
Example Response:
{
"id": 123,
"fingerprint": "abc123...",
"object_type": "post",
"object_id": 456,
"object_title": "My Blog Post",
"field": "post_content",
"rule_id": "ext_script_non_allowlist",
"category": "external_resources",
"severity": "critical",
"confidence": 90,
"matched_excerpt": "[script tag pointing to external domain]",
"domain": "suspicious-domain.example",
"first_seen": "2025-01-15T10:30:00Z",
"last_seen": "2025-01-15T10:30:00Z",
"status": "open",
"extra": {
"tag": "script",
"reputation": {
"service": "google_safe_browsing",
"threat": "UNSAFE"
}
}
}
Get Statistics #
GET /wp-json/content-guard-pro/v1/stats
Example Response:
{
"findings": {
"total": 45,
"open": 10,
"quarantined": 5,
"ignored": 20,
"resolved": 10
},
"by_severity": {
"critical": 3,
"suspicious": 7,
"review": 35
},
"last_scan": {
"scan_id": 789,
"started_at": "2025-01-15T03:00:00Z",
"finished_at": "2025-01-15T03:05:30Z",
"mode": "standard",
"items_checked": 1250,
"items_flagged": 5
},
"next_scheduled_scan": "2025-01-16T03:00:00Z"
}
Get Post Findings #
GET /wp-json/content-guard-pro/v1/post-findings/{post_id}
Example Response:
{
"findings": [...],
"counts": {
"critical": 1,
"suspicious": 2,
"review": 0
},
"total": 3,
"has_issues": true,
"has_critical": true,
"quarantined_count": 0,
"has_quarantined": false
}
Scan Post (Synchronous) #
POST /wp-json/content-guard-pro/v1/scan-post
Request Body:
{
"post_id": 123,
"content": "<p>Optional content to scan...</p>",
"manual": true
}
Parameters:
| Parameter | Type | Required | Description |
| ———– | —— | ———- | ————- |
post_id |
integer | Yes | Post ID to scan |
content |
string | No | Content to scan (uses post content if not provided) |
manual |
boolean | No | If true, runs regardless of auto-scan setting |
Example Response:
{
"success": true,
"findings": [...],
"counts": {
"critical": 0,
"suspicious": 1,
"review": 0
},
"has_critical": false
}
Get Active Scan Progress #
GET /wp-json/content-guard-pro/v1/scans/active
Example Response (scan running):
{
"active": true,
"scan_id": 790,
"mode": "standard",
"progress": 45,
"items_scanned": 450,
"items_total": 1000,
"current_phase": "postmeta",
"findings_count": 3,
"started_at": "2025-01-15T10:30:00Z",
"eta": "2025-01-15T10:35:00Z"
}
Example Response (no scan):
{
"active": false
}
Response Codes #
| Code | Meaning |
| —— | ——— |
| 200 | Success |
| 400 | Bad request (invalid parameters) |
| 401 | Authentication required |
| 403 | Permission denied |
| 404 | Resource not found |
| 429 | Rate limited |
| 500 | Server error |
Error Response Format #
{
"code": "rest_forbidden",
"message": "Sorry, you are not allowed to access this resource.",
"data": {
"status": 403
}
}
Rate Limiting #
| Context | Limit |
| ——— | ——- |
| Authenticated users | 60 requests/minute |
| Application passwords | 30 requests/minute |
Rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1642250400
Pagination #
List endpoints return pagination info:
{
"findings": [...],
"total": 150,
"pages": 3,
"page": 1
}
Use page and per_page parameters to navigate:
GET /findings?page=2&per_page=50
Filtering Examples #
All Critical Open Findings #
GET /findings?status=open&severity=critical
Post Findings Only #
GET /findings?object_type=post
Recent Findings (Last 24 Hours) #
GET /findings?after=2025-01-14T10:00:00Z
Using with JavaScript #
// In WordPress admin with wp-api-fetch
wp.apiFetch({
path: '/content-guard-pro/v1/findings?status=open'
}).then(response => {
console.log(response.findings);
});// External with Application Password
fetch('https://yoursite.com/wp-json/content-guard-pro/v1/stats', {
headers: {
'Authorization': 'Basic ' + btoa('admin:xxxx xxxx xxxx xxxx')
}
}).then(r => r.json()).then(data => console.log(data));
Using with PHP #
// From external script
$response = wp_remote_get(
'https://yoursite.com/wp-json/content-guard-pro/v1/findings',
array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode('admin:app_password')
)
)
);$data = json_decode(wp_remote_retrieve_body($response), true);