Security alerts WordPress 7.1.4 · no-login code execution in the updater 117 critical WordPress plugin CVEs · in October, most need no login

Developers · early access

InternetSecure API

Read your monitors and run security scans from scripts, CI pipelines and AI assistants. Every account gets API keys, free included; plans differ in limits.

Get an API key openapi.json Import it into Postman or editor.swagger.io.

Quick start

  1. Create a key in Settings → API keys. It's shown once.
  2. Check it works, then scan a site and fail a deploy below a grade:
export ISEC_KEY=isk_...

curl https://internetsecure.org/api/v1/me -H "Authorization: Bearer $ISEC_KEY"

curl -X POST https://internetsecure.org/api/v1/scans \
  -H "Authorization: Bearer $ISEC_KEY" \
  -d '{"domain": "example.com", "min_grade": "B"}'
# → "gate": {"min_grade": "B", "passed": true}

Use it from an AI assistant (MCP)

The MCP server at https://internetsecure.org/mcp gives Claude, Cursor and VS Code eight tools: get_account, list_monitors, get_monitor, get_security_result, run_scan, get_scan, add_monitor and update_monitor. It uses the same key, limits and scan quota as the API. With a read-only key it can only look and scan; with a full-access key it can add and change monitors (your assistant asks you first, and every change can be undone in the Activity Log). Removing monitors and connecting Slack, Teams, JIRA or Linear stay on the website.

Claude Code Run in a terminal, then start a new claude session:

claude mcp add --transport http internetsecure https://internetsecure.org/mcp \
  --header "Authorization: Bearer isk_YOUR_KEY"

Cursor Add to ~/.cursor/mcp.json:

{
    "mcpServers": {
        "internetsecure": {
            "url": "https://internetsecure.org/mcp",
            "headers": {
                "Authorization": "Bearer isk_YOUR_KEY"
            }
        }
    }
}

VS Code Add to .vscode/mcp.json:

{
    "servers": {
        "internetsecure": {
            "type": "http",
            "url": "https://internetsecure.org/mcp",
            "headers": {
                "Authorization": "Bearer isk_YOUR_KEY"
            }
        }
    }
}

Claude Desktop Settings → Developer → Edit Config, add (needs Node.js), then restart Claude:

{
    "mcpServers": {
        "internetsecure": {
            "command": "npx",
            "args": [
                "-y",
                "mcp-remote",
                "https://internetsecure.org/mcp",
                "--header",
                "Authorization:${AUTH_HEADER}"
            ],
            "env": {
                "AUTH_HEADER": "Bearer isk_YOUR_KEY"
            }
        }
    }
}

Auth

Every call sends Authorization: Bearer isk_…. Create keys in Settings → API keys on any plan, up to 10 per account (e.g. "GitHub Actions", "Claude"). A key is shown once and stored hashed; revoke it any time. Tick Read-only for keys that only read and scan, such as one for an AI assistant. There is no anonymous access.

Limits

PlanRequests/minScans/day
Free6010
Plus120100
Pro300500
Enterprise6002,000

Only POST /scans uses scan quota. Failed scans don't count. Headers: X-RateLimit-Remaining, X-Scans-Remaining, Retry-After.

Errors

Always the same shape, with a plain message an AI can repeat to the user:

{
    "error": {
        "code": "scan_quota",
        "message": "Used 10 of 10 scans today on Free. Resets 2026-11-07T00:00:00Z.",
        "docs": "https://internetsecure.org/docs/api#errors"
    }
}

Account

Who the key belongs to, the plan, and what is left of today's limits.

get /me Account, plan and remaining limits

Handy first call for an AI assistant: tells it what it can do before it tries.

Responses

  • 200 The account behind this key.
  • 401 Missing, wrong or revoked key. unauthorized

Example

curl https://internetsecure.org/api/v1/me \
  -H "Authorization: Bearer $ISEC_KEY"

Response 200

{
    "account": {
        "id": 1042,
        "email": "[email protected]",
        "plan": "pro"
    },
    "limits": {
        "monitors": {
            "used": 37,
            "max": 100
        },
        "requests_per_minute": 300,
        "scans_per_day": {
            "used": 12,
            "max": 500,
            "resets_at": "2026-11-07T00:00:00Z"
        }
    },
    "key": {
        "name": "GitHub Actions",
        "read_only": false,
        "created_at": "2026-11-01T09:00:00Z",
        "last_used_at": "2026-11-06T17:44:58Z"
    },
    "integrations": {
        "email": {
            "connected": true,
            "enabled": true,
            "settings_url": "https://internetsecure.org/account/profile?panel=email"
        },
        "slack": {
            "connected": true,
            "uptime_alerts": true,
            "security_alerts": true,
            "settings_url": "https://internetsecure.org/account/profile?panel=slack"
        },
        "teams": {
            "connected": false,
            "uptime_alerts": false,
            "security_alerts": false,
            "settings_url": "https://internetsecure.org/account/profile?panel=teams"
        },
        "jira": {
            "connected": false,
            "uptime_alerts": false,
            "security_alerts": false,
            "settings_url": "https://internetsecure.org/account/profile?panel=jira"
        },
        "linear": {
            "connected": false,
            "uptime_alerts": false,
            "security_alerts": false,
            "settings_url": "https://internetsecure.org/account/profile?panel=linear"
        }
    }
}

Monitors

The domains on your account: uptime checks and scheduled security scans. Same plan limits as the website.

get /monitors List monitors

Parameters

  • status query Only monitors in this uptime state.
  • search query Part of a domain name.
  • limit query
  • cursor query next_cursor from the previous page.

Responses

  • 200 A page of monitors.
  • 401 Missing, wrong or revoked key. unauthorized
  • 429 Too many requests this minute. rate_limited

Example

curl https://internetsecure.org/api/v1/monitors \
  -H "Authorization: Bearer $ISEC_KEY"

Response 200

{
    "data": [
        {
            "id": 48213,
            "domain": "example.com",
            "uptime": {
                "enabled": true,
                "status": "up",
                "last_checked_at": "2026-11-06T17:42:10Z",
                "response_ms": 212,
                "uptime_24h": 100,
                "uptime_30d": 99.97,
                "open_incident": null
            },
            "security": {
                "enabled": true,
                "schedule": "daily",
                "live": true,
                "grade": "B",
                "exposure_grade": "A",
                "last_scan_at": "2026-11-06T06:03:44Z"
            },
            "report_url": "https://internetsecure.org/account/uptime/48213"
        }
    ],
    "next_cursor": null
}
post /monitors Add a monitor

Adds a domain to the account, exactly like Monitors → Add on the website. New domains get daily security scans; paid plans also get the 2-hour live exposure check.

Responses

  • 201 Created.
  • 401 Missing, wrong or revoked key. unauthorized
  • 403 Plan limit reached (plan_limit), or the key is read-only (read_only_key). plan_limit
  • 409 Already on the account. already_exists
  • 422 Not a public domain. invalid_domain
  • 429 Too many requests this minute. rate_limited

Example

curl -X POST https://internetsecure.org/api/v1/monitors \
  -H "Authorization: Bearer $ISEC_KEY" \
  -d '{"domain":"example.com","uptime":true,"security_scans":true}'

Response 201

{
    "id": 48213,
    "domain": "example.com",
    "uptime": {
        "enabled": true,
        "status": "up",
        "last_checked_at": "2026-11-06T17:42:10Z",
        "response_ms": 212,
        "uptime_24h": 100,
        "uptime_30d": 99.97,
        "open_incident": null
    },
    "security": {
        "enabled": true,
        "schedule": "daily",
        "live": true,
        "grade": "B",
        "exposure_grade": "A",
        "last_scan_at": "2026-11-06T06:03:44Z"
    },
    "report_url": "https://internetsecure.org/account/uptime/48213"
}
get /monitors/{id} Get one monitor

Parameters

  • id path Monitor id (from GET /monitors).

Responses

  • 200 The monitor.
  • 404 No such id on this account. not_found

Example

curl https://internetsecure.org/api/v1/monitors/48213 \
  -H "Authorization: Bearer $ISEC_KEY"

Response 200

{
    "id": 48213,
    "domain": "example.com",
    "uptime": {
        "enabled": true,
        "status": "up",
        "last_checked_at": "2026-11-06T17:42:10Z",
        "response_ms": 212,
        "uptime_24h": 100,
        "uptime_30d": 99.97,
        "open_incident": null
    },
    "security": {
        "enabled": true,
        "schedule": "daily",
        "live": true,
        "grade": "B",
        "exposure_grade": "A",
        "last_scan_at": "2026-11-06T06:03:44Z"
    },
    "report_url": "https://internetsecure.org/account/uptime/48213"
}
patch /monitors/{id} Change or pause a monitor

Send only the fields you want to change. To pause uptime checks during a deploy: {"uptime": false}, then {"uptime": true} after. Pausing keeps the check and its history. alerts applies to every check on the monitor. Every change shows in the account's Activity Log, where it can be undone. Monitors can only be removed on the website.

Parameters

  • id path Monitor id (from GET /monitors).

Responses

  • 200 Updated.
  • 403 The key is read-only. read_only_key
  • 404 No such id on this account. not_found
  • 422 Bad field. invalid_field

Example

curl -X PATCH https://internetsecure.org/api/v1/monitors/48213 \
  -H "Authorization: Bearer $ISEC_KEY" \
  -d '{"uptime":false}'

Response 200

{
    "id": 48213,
    "domain": "example.com",
    "uptime": {
        "enabled": false,
        "status": "paused",
        "last_checked_at": "2026-11-06T17:42:10Z",
        "response_ms": 212,
        "uptime_24h": 100,
        "uptime_30d": 99.97,
        "open_incident": null
    },
    "security": {
        "enabled": true,
        "schedule": "daily",
        "live": true,
        "grade": "B",
        "exposure_grade": "A",
        "last_scan_at": "2026-11-06T06:03:44Z"
    },
    "report_url": "https://internetsecure.org/account/uptime/48213"
}
get /monitors/{id}/security Latest security result for a monitor

The most recent scheduled or live scan, with every check. Does not run a new scan and does not use scan quota.

Parameters

  • id path Monitor id (from GET /monitors).

Responses

  • 200 Latest result.
  • 404 No such monitor on this account, or it has no scan yet (code not_scanned). not_found

Example

curl https://internetsecure.org/api/v1/monitors/48213/security \
  -H "Authorization: Bearer $ISEC_KEY"

Response 200

{
    "id": 9918231,
    "domain": "example.com",
    "scanned_at": "2026-11-06T17:45:02Z",
    "duration_ms": 3810,
    "security": {
        "grade": "B",
        "score": 78,
        "passed": 8,
        "warnings": 3,
        "failed": 1
    },
    "exposure": {
        "grade": "A",
        "findings": []
    },
    "checks": [
        {
            "id": "ssl",
            "name": "SSL certificate",
            "status": "pass",
            "detail": "Valid, expires 2027-01-15 (70 days)"
        },
        {
            "id": "mixed_content",
            "name": "Mixed content",
            "status": "pass",
            "detail": "None found"
        },
        {
            "id": "hsts",
            "name": "HSTS",
            "status": "pass",
            "detail": "max-age=31536000"
        },
        {
            "id": "x_frame_options",
            "name": "X-Frame-Options",
            "status": "fail",
            "detail": "Missing"
        },
        {
            "id": "csp",
            "name": "Content-Security-Policy",
            "status": "warn",
            "detail": "Missing"
        },
        {
            "id": "tls",
            "name": "TLS",
            "status": "pass",
            "detail": "TLS 1.3, strong cipher"
        },
        {
            "id": "security_headers",
            "name": "Security headers",
            "status": "pass",
            "detail": "4 of 6 present"
        },
        {
            "id": "cookies",
            "name": "Cookies",
            "status": "pass",
            "detail": "Secure and HttpOnly"
        },
        {
            "id": "dmarc",
            "name": "DMARC",
            "status": "pass",
            "detail": "p=reject"
        },
        {
            "id": "dkim",
            "name": "DKIM",
            "status": "warn",
            "detail": "No record on common selectors"
        },
        {
            "id": "dnssec",
            "name": "DNSSEC",
            "status": "warn",
            "detail": "Not enabled"
        },
        {
            "id": "server_version",
            "name": "Server version",
            "status": "pass",
            "detail": "Not announced"
        },
        {
            "id": "waf",
            "name": "WAF",
            "status": "info",
            "detail": "None announced (not scored)"
        }
    ],
    "previous": {
        "scan_id": 9917004,
        "grade": "A",
        "exposure_grade": "A",
        "scanned_at": "2026-11-06T06:02:11Z"
    },
    "changes": [
        {
            "check": "csp",
            "name": "Content-Security-Policy",
            "from": "pass",
            "to": "warn",
            "worse": true
        }
    ],
    "report_url": "https://internetsecure.org/account/scan/9918231",
    "monitor_id": 48213
}

Scans

Run a security scan now, e.g. as a deploy check in CI. Counts against the daily scan quota.

post /scans Run a security scan now

Scans any public domain (it does not have to be a monitor) and waits for the result, usually 2–10 seconds. Uses 1 from the daily scan quota. For CI: pass min_grade and/or no_drop and check gate.passed (fail the build when false); gate.reason is a one-line explanation for the build log. Every result also says what changed since your previous scan of the domain.

Responses

  • 200 Scan finished.
  • 401 Missing, wrong or revoked key. unauthorized
  • 422 Not a public domain. invalid_domain
  • 429 Daily scan quota used up (or too many requests). scan_quota
  • 502 The site could not be scanned (no answer, DNS failure). scan_failed
  • 503 Scanners are busy; retry after the Retry-After header. busy

Example

curl -X POST https://internetsecure.org/api/v1/scans \
  -H "Authorization: Bearer $ISEC_KEY" \
  -d '{"domain":"example.com","min_grade":"B"}'

Response 200

{
    "id": 9918231,
    "domain": "example.com",
    "scanned_at": "2026-11-06T17:45:02Z",
    "duration_ms": 3810,
    "security": {
        "grade": "B",
        "score": 78,
        "passed": 8,
        "warnings": 3,
        "failed": 1
    },
    "exposure": {
        "grade": "A",
        "findings": []
    },
    "checks": [
        {
            "id": "ssl",
            "name": "SSL certificate",
            "status": "pass",
            "detail": "Valid, expires 2027-01-15 (70 days)"
        },
        {
            "id": "mixed_content",
            "name": "Mixed content",
            "status": "pass",
            "detail": "None found"
        },
        {
            "id": "hsts",
            "name": "HSTS",
            "status": "pass",
            "detail": "max-age=31536000"
        },
        {
            "id": "x_frame_options",
            "name": "X-Frame-Options",
            "status": "fail",
            "detail": "Missing"
        },
        {
            "id": "csp",
            "name": "Content-Security-Policy",
            "status": "warn",
            "detail": "Missing"
        },
        {
            "id": "tls",
            "name": "TLS",
            "status": "pass",
            "detail": "TLS 1.3, strong cipher"
        },
        {
            "id": "security_headers",
            "name": "Security headers",
            "status": "pass",
            "detail": "4 of 6 present"
        },
        {
            "id": "cookies",
            "name": "Cookies",
            "status": "pass",
            "detail": "Secure and HttpOnly"
        },
        {
            "id": "dmarc",
            "name": "DMARC",
            "status": "pass",
            "detail": "p=reject"
        },
        {
            "id": "dkim",
            "name": "DKIM",
            "status": "warn",
            "detail": "No record on common selectors"
        },
        {
            "id": "dnssec",
            "name": "DNSSEC",
            "status": "warn",
            "detail": "Not enabled"
        },
        {
            "id": "server_version",
            "name": "Server version",
            "status": "pass",
            "detail": "Not announced"
        },
        {
            "id": "waf",
            "name": "WAF",
            "status": "info",
            "detail": "None announced (not scored)"
        }
    ],
    "previous": {
        "scan_id": 9917004,
        "grade": "A",
        "exposure_grade": "A",
        "scanned_at": "2026-11-06T06:02:11Z"
    },
    "changes": [
        {
            "check": "csp",
            "name": "Content-Security-Policy",
            "from": "pass",
            "to": "warn",
            "worse": true
        }
    ],
    "gate": {
        "min_grade": "B",
        "no_drop": true,
        "passed": false,
        "reason": "Grade dropped A → B: Content-Security-Policy pass → warn"
    },
    "report_url": "https://internetsecure.org/account/scan/9918231"
}
get /scans/{id} Fetch an earlier scan

Only scans run by this account.

Parameters

  • id path Scan id from POST /scans.

Responses

  • 200 The scan.
  • 404 No such id on this account. not_found

Example

curl https://internetsecure.org/api/v1/scans/9918231 \
  -H "Authorization: Bearer $ISEC_KEY"

Response 200

{
    "id": 9918231,
    "domain": "example.com",
    "scanned_at": "2026-11-06T17:45:02Z",
    "duration_ms": 3810,
    "security": {
        "grade": "B",
        "score": 78,
        "passed": 8,
        "warnings": 3,
        "failed": 1
    },
    "exposure": {
        "grade": "A",
        "findings": []
    },
    "checks": [
        {
            "id": "ssl",
            "name": "SSL certificate",
            "status": "pass",
            "detail": "Valid, expires 2027-01-15 (70 days)"
        },
        {
            "id": "mixed_content",
            "name": "Mixed content",
            "status": "pass",
            "detail": "None found"
        },
        {
            "id": "hsts",
            "name": "HSTS",
            "status": "pass",
            "detail": "max-age=31536000"
        },
        {
            "id": "x_frame_options",
            "name": "X-Frame-Options",
            "status": "fail",
            "detail": "Missing"
        },
        {
            "id": "csp",
            "name": "Content-Security-Policy",
            "status": "warn",
            "detail": "Missing"
        },
        {
            "id": "tls",
            "name": "TLS",
            "status": "pass",
            "detail": "TLS 1.3, strong cipher"
        },
        {
            "id": "security_headers",
            "name": "Security headers",
            "status": "pass",
            "detail": "4 of 6 present"
        },
        {
            "id": "cookies",
            "name": "Cookies",
            "status": "pass",
            "detail": "Secure and HttpOnly"
        },
        {
            "id": "dmarc",
            "name": "DMARC",
            "status": "pass",
            "detail": "p=reject"
        },
        {
            "id": "dkim",
            "name": "DKIM",
            "status": "warn",
            "detail": "No record on common selectors"
        },
        {
            "id": "dnssec",
            "name": "DNSSEC",
            "status": "warn",
            "detail": "Not enabled"
        },
        {
            "id": "server_version",
            "name": "Server version",
            "status": "pass",
            "detail": "Not announced"
        },
        {
            "id": "waf",
            "name": "WAF",
            "status": "info",
            "detail": "None announced (not scored)"
        }
    ],
    "previous": {
        "scan_id": 9917004,
        "grade": "A",
        "exposure_grade": "A",
        "scanned_at": "2026-11-06T06:02:11Z"
    },
    "changes": [
        {
            "check": "csp",
            "name": "Content-Security-Policy",
            "from": "pass",
            "to": "warn",
            "worse": true
        }
    ],
    "report_url": "https://internetsecure.org/account/scan/9918231"
}