Security Center APIPublic Developer Documentation
MEDPOV Remote Access API

Public developer area for Security Center.

This page explains how remote websites, backend services, local assistants and automation tools can call the MEDPOV Security Center API. The API is designed for querying security events, building IP profiles, watching live traffic, reading system health and running authorized POST actions.

18Read / query action
7Authorized POST action
OffQuery string API key mode
JSONResponse format
Action discovery is synchronized from docs/openapi.yaml (20 declared GET actions). Narrative examples below add usage guidance to that canonical contract.

Auth and connection standard

Create the API key from the Remote API Access section on the Settings page. The key is shown as plain text only once when created; afterwards it is stored as a hash.

Recommended header

Authorization + Tenant Scope
Authorization: Bearer mpsec_YOUR_API_KEY
X-MEDPOV-Site-ID: site_xxxxxxxxx
Accept: application/json

Alternatively, X-MEDPOV-API-Key: mpsec_YOUR_API_KEY or X-API-Key can be used. Query-string API keys are permanently disabled.

HTTP and response rules

  • All responses return application/json; charset=utf-8.
  • GET actions read information; POST actions modify IP rules or event status.
  • CORS is deny-by-default: browser requests with Origin are accepted only when listed in allowed_origins; native/server clients may call without Origin.
  • Successful responses usually return ok: true; errors return ok: false.
Important: Do not place the API key directly inside public JavaScript, HTML source code or a mobile app. If a remote website needs to call the API, call it through your own backend proxy/helper.

Multi-Site Flow

  1. GET action=sites — authenticate globally; omit the site header.
  2. Select the returned site_... identity.
  3. Send X-MEDPOV-Site-ID on every site-scoped read, analyze and write request.
  4. Use GET action=all-sites-overview for the global fleet view; omit the site header.
Discover Sites
curl 'https://guard.medpov.com/admin/api/remote-access.php?action=sites' \
  -H 'Authorization: Bearer mpsec_YOUR_API_KEY'

curl 'https://guard.medpov.com/admin/api/remote-access.php?action=all-sites-overview' \
  -H 'Authorization: Bearer mpsec_YOUR_API_KEY'

Queryable commands

These actions can be called from a remote system or local assistant. Read actions work with GET.

ActionMethodParametersReturns
ping / statusGETValidates the API key, connection, version and server time.
capabilities / schemaGETReturns supported actions and basic authentication information.
sites / protected-sitesGETReturns selectable site identities using the global Control Center key; no site header is required.
all-sites-overviewGETReturns a fleet overview; no site header is required.
overview / dashboardGETReturns dashboard summary, site details, 24-hour top IP list, latest HIGH/CRITICAL events and recommendations.
map / map-data / map-intelligenceGETmode, threat_range, live_range, include_curve_pointsReturns the same target, threat_events, live_users, layers, traces, popups and active mode data used by the dashboard map.
threat-map / live-map / both-mapGETthreat_range, live_range, include_curve_pointsShortcut aliases for opening the map directly in Threat, Live or Both mode.
threats / latest-threatsGETlimitReturns the latest high-risk threat stream.
eventsGETrisk, status, ip, q, since_hours, resolved, limit, offsetLists security events with filtering and pagination.
eventGETidReturns one security event with details, IP rule status and quick analysis.
ip / ip-profile / ip_profileGETip, refresh, limitBuilds an IP profile with lookup, DNSBL, traffic, login pressure, bot records, AI traces and recommendations.
analyze / analysisGETip or event_idReturns signal summary, rule status and recommendation for an IP or event.
trafficGETip, q, since_hours, limitReturns recent traffic records.
live / live-sessionsGETlimitReturns active heartbeat/live session list.
botsGETip, q, limitLists bot detections and bot scores.
login / login-pressureGETip, q, limitReturns admin/user login pressure and failed login records.
healthGETFor remote sites, returns the latest Agent security_health/diagnostics snapshot; run an Agent health job first when fresh data is required.
settingsGETReturns a safe system/module settings summary without secret keys.

Map access and Friday map commands

The map endpoint follows the same logic as the Global Threat Map in the admin dashboard. Friday can read attack locations, live visitor points, trace lines going to the protected target and click-popup fields from this JSON response.

Map mode options

GET action=map&mode=threat&threat_range=24hOnly attack locations, threat markers, attack trace lines and threat popup fields.
GET action=map&mode=live&live_range=liveActive heartbeat visitors, live markers, visitor trace lines and live popup fields.
GET action=map&mode=both&live_range=liveThreat and Live layers are both active in the same map response.
GET action=both-map&include_curve_points=1Shortcut alias; Friday can redraw the curved lines with curve_points.
GET action=map&mode=both&include_curve_points=0Lighter response; line from/to + style is returned without curve points.
Main Map JSON fields
{
  "ok": true,
  "access": "map-intelligence",
  "mode": "both",
  "target": { "lat": 41.0082, "lng": 28.9784, "label": "Protected Origin" },
  "threat_events": [],
  "live_users": [],
  "layers": {
    "threat": { "enabled": true, "points": [], "traces": [], "popups": [] },
    "live": { "enabled": true, "points": [], "traces": [], "popups": [] }
  },
  "map": {
    "provider": "leaflet",
    "tile_provider": "openstreetmap",
    "tile_url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
    "active_layers": ["threat", "live"],
    "popup_contract": {}
  }
}

Authorized POST actions

These commands modify the system. They should only be called from a trusted backend, local assistant or automation service.

ActionMethodBody parametersWhat it does
block-ipPOSTip, minutes, reasonCreates a temporary or permanent block rule for the given IP.
allow-ipPOSTip, minutes, reasonCreates an allow rule for the given IP.
ignore-ipPOSTip, minutes, reasonExcludes the given IP from tracking/action pressure.
expire-ip-rules / remove-ip-rulesPOSTip, rule_typeExpires active block/allow/ignore rules for the IP.
resolve-eventPOSTid, statusMarks one event as resolved.
resolve-ip-eventsPOSTip, statusBulk-resolves open events for an IP.
ai-recheckPOSTlimitRuns a Local AI re-check batch.

Remote website call examples

The endpoint remains fixed; only action and parameters change. In the examples below, replace mpsec_YOUR_API_KEY with the key generated from Settings.

cURL · Overview
curl -X GET 'https://guard.medpov.com/admin/api/remote-access.php?action=overview' \
  -H 'Authorization: Bearer mpsec_YOUR_API_KEY' \
  -H 'X-MEDPOV-Site-ID: site_xxxxxxxxx'
  -H 'Accept: application/json'
cURL · Map / Both
curl -X GET 'https://guard.medpov.com/admin/api/remote-access.php?action=both-map&limit=500' \
+  -H 'Authorization: Bearer mpsec_YOUR_API_KEY' \
+  -H 'X-MEDPOV-Site-ID: site_xxxxxxxxx'
  -H 'Accept: application/json'
cURL · Block IP
curl -X POST 'https://guard.medpov.com/admin/api/remote-access.php?action=block-ip' \
  -H 'Authorization: Bearer mpsec_YOUR_API_KEY' \
  -H 'X-MEDPOV-Site-ID: site_xxxxxxxxx'
  -H 'Content-Type: application/json' \
  -d '{"ip":"203.0.113.45","minutes":1440,"reason":"Remote confirmed abusive traffic"}'
PHP helper · remote site/backend
<?php
function medpov_security_api(string $endpoint, string $apiKey, string $siteId, string $action, array $params = [], string $method = 'GET'): array
{
    $method = strtoupper($method);
    $url = $endpoint . '?action=' . rawurlencode($action);

    $headers = [
        'Authorization: Bearer ' . $apiKey,
        'Accept: application/json',
    ];
    if ($siteId !== '') $headers[] = 'X-MEDPOV-Site-ID: ' . $siteId;

    $body = null;
    if ($method === 'GET' && $params) {
        $url .= '&' . http_build_query($params);
    } elseif ($params) {
        $headers[] = 'Content-Type: application/json';
        $body = json_encode($params, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    }

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_CONNECTTIMEOUT => 8,
    ]);

    if ($body !== null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
    }

    $raw = curl_exec($ch);
    $error = curl_error($ch);
    $status = (int)curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);

    if ($raw === false || $raw === '') {
        return ['ok' => false, 'status' => $status, 'message' => $error ?: 'Empty API response'];
    }

    $json = json_decode($raw, true);
    if (!is_array($json)) {
        return ['ok' => false, 'status' => $status, 'message' => 'Invalid JSON response', 'raw' => $raw];
    }

    $json['_http_status'] = $status;
    return $json;
}

$endpoint = 'https://example.com/security-center/admin/api/remote-access.php';
$apiKey = 'mpsec_YOUR_API_KEY';
$siteId = 'site_xxxxxxxxx'; // Discover with GET action=sites (without this header).

$overview = medpov_security_api($endpoint, $apiKey, $siteId, 'overview');
$ipProfile = medpov_security_api($endpoint, $apiKey, $siteId, 'ip-profile', ['ip' => '8.8.8.8', 'refresh' => 1]);
$block = medpov_security_api($endpoint, $apiKey, $siteId, 'block-ip', [
    'ip' => '203.0.113.45',
    'minutes' => 1440,
    'reason' => 'Remote confirmed abusive traffic',
], 'POST');
Node / server-side fetch
const endpoint = 'https://example.com/security-center/admin/api/remote-access.php';
const apiKey = process.env.MEDPOV_SECURITY_API_KEY;
const siteId = process.env.MEDPOV_SECURITY_SITE_ID;

async function securityApi(action, params = {}, method = 'GET') {
  const url = new URL(endpoint);
  url.searchParams.set('action', action);

  const options = {
    method,
    headers: {
      Authorization: `Bearer ${apiKey}`,
      Accept: 'application/json'
    }
  };
  if (siteId) options.headers['X-MEDPOV-Site-ID'] = siteId;

  if (method === 'GET') {
    Object.entries(params).forEach(([key, value]) => url.searchParams.set(key, String(value)));
  } else {
    options.headers['Content-Type'] = 'application/json';
    options.body = JSON.stringify(params);
  }

  const res = await fetch(url, options);
  const data = await res.json();
  if (!res.ok || data.ok === false) throw new Error(data.message || `API error ${res.status}`);
  return data;
}

const overview = await securityApi('overview');
const mapBoth = await securityApi('map', { mode: 'both', live_range: 'live', include_curve_points: 1 });
const critical = await securityApi('events', { risk: 'CRITICAL', resolved: 0, limit: 20 });

Example response format

Each action returns its own detail fields; the shared success/error logic is shown below.

Success shape
{
  "ok": true,
  "scope": "protected_site",
  "version": "9.0.0",
  "site": {
    "id": "site_xxxxxxxxx",
    "name": "Example",
    "domain": "example.com"
  }
}
Map shape
{
  "ok": true,
  "access": "map-intelligence",
  "mode": "both",
  "target": { "lat": 41.0082, "lng": 28.9784, "label": "Protected Origin" },
  "threat_events": [],
  "live_users": [],
  "layers": {
    "threat": { "enabled": true, "points": [], "traces": [], "popups": [] },
    "live": { "enabled": true, "points": [], "traces": [], "popups": [] }
  },
  "map": {
    "provider": "leaflet",
    "tile_provider": "openstreetmap",
    "tile_url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
    "active_layers": ["threat", "live"],
    "popup_contract": {}
  }
}
Error shape
{
  "ok": false,
  "message": "Unauthorized",
  "hint": "Send Authorization: Bearer <api-key> or X-MEDPOV-API-Key."
}

Local assistant / automation command mapping

Friday or a similar local assistant can translate user commands into the API actions below.

Summarize the Security status.GET action=overview
Fetch the latest critical events.GET action=events&risk=CRITICAL&resolved=0&limit=20
Open the map in threat mode.GET action=threat-map&threat_range=24h
Open the live map.GET action=live-map&live_range=live
Show threat and live together on the map.GET action=both-map&live_range=live&include_curve_points=1
Analyze IP 8.8.8.8 in detail.GET action=ip-profile&ip=8.8.8.8&refresh=1
Inspect event number 123.GET action=event&id=123
Block this IP for 24 hours.POST action=block-ip body: ip, minutes=1440, reason
Close open events for this IP.POST action=resolve-ip-events body: ip, status=remote_ip_resolved
Check system health.GET action=health

Secure usage

Store the API key only in a server-side environment variable. If the key leaks, disable it from Settings and generate a new one.

Rate and timeout

Use an 8-20 second timeout, short-lived cache and controlled retry on the remote helper side. Do not call health/overview in an endless loop.

Recommended flow

Start with ping, then overview. If there is risk, call events or ip-profile. Use POST actions only when necessary.

Setup note: Public documentation URL is https://guard.medpov.com/developer-api.php. The API endpoint is https://guard.medpov.com/admin/api/remote-access.php.
Copied