Skip to main contentSkip to footer

API Reference

Complete reference for all ReportedIP REST API v2 endpoints with code examples in cURL, PHP, Python, and JavaScript.

Daily quotas per tier: Free 1,000 checks · 50 reports · Contributor 5,000 / 200 · Professional 25,000 / 1,000 · Business 100,000 / 5,000 per licence · Enterprise unlimited. Business quotas scale with the licence count (x2–x20), e.g. x5 = 500,000 / 25,000. See Pricing for the full tier comparison.
Base URL https://reportedip.de/wp-json/reportedip/v2/
Authentication: Authenticated endpoints require an API key sent via the X-Key header. Public endpoints do not require authentication but are rate-limited.
How quotas are counted (since v2.5.1): Each endpoint charges at most one daily counter, never both.
  • Check quota: GET /check (+1) and POST /bulk-check (+N, one per valid IP).
  • Report quota: POST /report (+1) and POST /bulk-report (+N, one per submitted report).
  • Neither quota: GET /blacklist, /blacklist-categories, /blacklist-stats, /reports/{ip}, /trends, /statistics, /verify-key — these are tier-gated features, not metered calls.
  • Public IP limit: 100 requests/day per source IP, shared across all unauthenticated calls (/check-public, /stats-public, /search-public, /categories, /attack-map-data). Send an X-Key header to switch to the API-key quota path instead.

Public Endpoints

These endpoints are available without authentication. Rate-limited to 100 requests per day per IP address.

GET /check-public
Public

Check the reputation of an IP address without authentication. Returns abuse confidence score, total reports, threat categories, and last report date. Counts +1 against the per-IP public-API daily limit (shared with the other unauthenticated endpoints).

Public limit: 100 requests/day per source IP, shared across all unauthenticated endpoints. Send an X-Key header to switch to the API-key quota path.

Parameters

Name Type Required Default Description
ip string Yes IPv4 or IPv6 address to check
verbose boolean No false Include detailed confidence breakdown in response

Examples

curl
curl "https://reportedip.de/wp-json/reportedip/v2/check-public?ip=1.2.3.4"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/check-public?ip=1.2.3.4'
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/check-public',
    params={'ip': '1.2.3.4'}
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/check-public?ip=1.2.3.4'
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "ip": "1.2.3.4",
    "abuseConfidencePercentage": 87,
    "totalReports": 42,
    "lastReportedAt": "2026-03-09T14:22:31Z",
    "categories": [18, 21, 22],
    "countryCode": "CN",
    "isp": "China Telecom"
  }
}
GET /stats-public
Public

Retrieve extended public statistics with category breakdowns, top threat types, and historical data. Counts +1 against the per-IP public-API daily limit.

Public limit: 100 requests/day per source IP, shared across all unauthenticated endpoints.

Examples

curl
curl "https://reportedip.de/wp-json/reportedip/v2/stats-public"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/stats-public'
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/stats-public'
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/stats-public'
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "totalIPs": 158432,
    "totalReports": 892741,
    "last24h": {
      "newIPs": 342,
      "newReports": 1847
    },
    "last7d": {
      "newIPs": 2156,
      "newReports": 12493
    },
    "categoryBreakdown": [
      {"id": 18, "name": "Brute-Force", "count": 45231},
      {"id": 21, "name": "Web App Attack", "count": 32198},
      {"id": 22, "name": "SSH", "count": 28764},
      {"id": 15, "name": "Port Scan", "count": 18432}
    ],
    "topCountries": [
      {"code": "CN", "count": 42156},
      {"code": "US", "count": 18743},
      {"code": "RU", "count": 15892}
    ]
  }
}
GET /search-public
Public

Search the public reputation database by partial IP, country code, or ASN. Useful for the public-facing search bar on reportedip.de. Counts +1 against the per-IP public-API daily limit.

Public limit: 100 requests/day per source IP, shared across all unauthenticated endpoints. Results are capped at 50 entries per call.

Parameters

Name Type Required Default Description
q string Yes Search query: full or partial IP, country code (e.g. "CN"), or ASN.
limit int No 20 Number of results (max 50).

Examples

curl
curl "https://reportedip.de/wp-json/reportedip/v2/search-public?q=1.2.3"

Response

200 OK
json
{
  "meta": {"success": true, "code": 200},
  "data": {
    "query": "1.2.3",
    "results": [
      {"ip": "1.2.3.4", "abuseConfidencePercentage": 87, "totalReports": 42, "countryCode": "CN"},
      {"ip": "1.2.3.5", "abuseConfidencePercentage": 65, "totalReports": 12, "countryCode": "CN"}
    ]
  }
}
GET /categories
Public

Retrieve the list of all 30 predefined threat categories used for classifying IP reports. Each category includes its ID, name, description, and severity level. Counts +1 against the per-IP public-API daily limit when called without an API key; with an X-Key header it does not count against any daily quota.

Public limit: 100 requests/day per source IP, shared across all unauthenticated endpoints. Send an X-Key header to bypass the public limit (no per-call quota when authenticated).

Examples

curl
curl "https://reportedip.de/wp-json/reportedip/v2/categories"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/categories'
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/categories'
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/categories'
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": [
    {
      "id": 1,
      "name": "DNS Compromise",
      "description": "Compromised DNS server or DNS hijacking",
      "severity_level": 8
    },
    {
      "id": 18,
      "name": "Brute-Force",
      "description": "Login brute-force attempts",
      "severity_level": 7
    },
    {
      "id": 21,
      "name": "Web App Attack",
      "description": "Web application attacks (SQLi, XSS, etc.)",
      "severity_level": 9
    }
  ]
}
GET /attack-map-data
Public

Aggregated dataset that powers the live attack map on reportedip.de. Returns per-country report counts (top 50), the rolling 24-hour set of cross-country attack connections (top 30, same-country pairs excluded) and a today-logs counter. Cached server-side for 30 minutes — repeat calls within that window all hit the cache. Counts +1 against the per-IP public-API daily limit.

Public limit: 100 requests/day per source IP, shared across all unauthenticated endpoints. Response is cached server-side for 30 minutes, so a polling client should respect that interval.

Examples

curl
curl "https://reportedip.de/wp-json/reportedip/v2/attack-map-data"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/attack-map-data'
);
$data = json_decode( wp_remote_retrieve_body( $response ), true );
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/attack-map-data'
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/attack-map-data'
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "country_data": {
      "CN": { "count": 42156, "avgThreat": 7.8 },
      "US": { "count": 18743, "avgThreat": 5.4 },
      "RU": { "count": 15892, "avgThreat": 7.1 }
    },
    "country_info": { },
    "total_reports": 76791,
    "max_reports": 42156,
    "recent_attacks": [
      {
        "id": 1,
        "source_country": "CN",
        "target_country": "DE",
        "confidence_score": 88,
        "attack_count": 214
      }
    ],
    "today_logs": 1847
  }
}

Authenticated Endpoints

These endpoints require a valid API key sent via the X-Key header. Get your API key from the Dashboard.

GET /check
API Key

Perform a full IP reputation check with detailed data. Returns comprehensive threat data including confidence breakdown, report history, and ISP information. Charges +1 against your daily check quota.

Parameters

Name Type Required Default Description
ip string Yes IPv4 or IPv6 address to check
verbose boolean No false Include detailed confidence score breakdown
include_reports boolean No false Include individual report details in response

Examples

curl
curl -H "X-Key: YOUR_API_KEY" \
     "https://reportedip.de/wp-json/reportedip/v2/check?ip=1.2.3.4&verbose=true"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/check?ip=1.2.3.4&verbose=true',
    array(
        'headers' => array(
            'X-Key' => 'YOUR_API_KEY',
        ),
    )
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/check',
    params={'ip': '1.2.3.4', 'verbose': 'true'},
    headers={'X-Key': 'YOUR_API_KEY'}
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/check?ip=1.2.3.4&verbose=true',
    {
        headers: { 'X-Key': 'YOUR_API_KEY' }
    }
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "ip": "1.2.3.4",
    "abuseConfidencePercentage": 87,
    "totalReports": 42,
    "lastReportedAt": "2026-03-09T14:22:31Z",
    "categories": [18, 21, 22],
    "countryCode": "CN",
    "isp": "China Telecom",
    "isWhitelisted": false,
    "confidenceBreakdown": {
      "reportScore": 24.0,
      "diversityScore": 12.0,
      "recencyWeight": 13.5,
      "severityWeight": 12.3,
      "honeypotBonus": 25.0,
      "maxConfidence": 100,
      "constraintReasons": []
    },
    "debugInfo": {
      "reportCount": 42,
      "uniqueReporters": 8,
      "honeypotReportsCount": 5,
      "effectiveReportCount": 47,
      "timeDampeningFactor": 0.92
    }
  }
}
POST /report
API Key

Report a malicious IP address to the community. The report will be aggregated with existing data to update the IP's abuse confidence score. Reports from the same reporter for the same IP within 5 minutes are automatically aggregated. Charges +1 against your daily report quota only — never against the check quota.

Parameters

Name Type Required Default Description
ip string Yes IPv4 or IPv6 address to report
categories array Yes Array of threat category IDs (e.g. [18, 21])
comment string No Optional comment describing the observed malicious activity

Examples

curl
curl -X POST \
     -H "X-Key: YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"ip": "1.2.3.4", "categories": [18, 21], "comment": "SSH brute force"}' \
     "https://reportedip.de/wp-json/reportedip/v2/report"
php
$response = wp_remote_post(
    'https://reportedip.de/wp-json/reportedip/v2/report',
    array(
        'headers' => array(
            'X-Key'        => 'YOUR_API_KEY',
            'Content-Type' => 'application/json',
        ),
        'body' => wp_json_encode(array(
            'ip'         => '1.2.3.4',
            'categories' => array(18, 21),
            'comment'    => 'SSH brute force',
        )),
    )
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.post(
    'https://reportedip.de/wp-json/reportedip/v2/report',
    json={
        'ip': '1.2.3.4',
        'categories': [18, 21],
        'comment': 'SSH brute force'
    },
    headers={'X-Key': 'YOUR_API_KEY'}
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/report',
    {
        method: 'POST',
        headers: {
            'X-Key': 'YOUR_API_KEY',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            ip: '1.2.3.4',
            categories: [18, 21],
            comment: 'SSH brute force'
        })
    }
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "Report submitted successfully"
  },
  "data": {
    "reportId": 58234,
    "ip": "1.2.3.4",
    "categories": [18, 21],
    "abuseConfidencePercentage": 89
  }
}
GET /verify-key
API Key

Verify your API key and retrieve account details including user role, permissions, rate limits, and current usage statistics. Does not count against any daily quota.

Examples

curl
curl -H "X-Key: YOUR_API_KEY" \
     "https://reportedip.de/wp-json/reportedip/v2/verify-key"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/verify-key',
    array(
        'headers' => array(
            'X-Key' => 'YOUR_API_KEY',
        ),
    )
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/verify-key',
    headers={'X-Key': 'YOUR_API_KEY'}
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/verify-key',
    {
        headers: { 'X-Key': 'YOUR_API_KEY' }
    }
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "valid": true,
    "role": "reportedip_professional",
    "permissions": {
      "check": true,
      "report": true,
      "bulk_check": true,
      "bulk_report": false,
      "reports_detail": true,
      "trends": true
    },
    "rateLimits": {
      "checksPerDay": 25000,
      "reportsPerDay": 1000
    },
    "usage": {
      "checksToday": 1247,
      "reportsToday": 38
    }
  }
}
GET /statistics
Authenticated

Authenticated per-user usage statistics: API calls today, reports today, total reports, verified reports, current reputation score, plus tier-specific quota usage. Does not count against any daily quota.

Parameters

Name Type Required Default Description
period string No today One of <code>today</code>, <code>week</code>, <code>month</code>, <code>all</code>.

Examples

curl
curl -H "X-Key: YOUR_KEY" "https://reportedip.de/wp-json/reportedip/v2/statistics?period=today"

Response

200 OK
json
{
  "meta": {"success": true, "code": 200},
  "data": {
    "apiCallsToday": 1247,
    "reportsToday": 38,
    "totalReports": 4271,
    "verifiedReports": 3892,
    "reputationScore": 87,
    "tier": "professional",
    "limits": {"checks": 25000, "reports": 1000}
  }
}

Blacklist Endpoints

Access the community-driven IP blacklist, automatically scored from real-time reports. Available in JSON, plain text, and CSV formats for firewall integration.

GET /blacklist
API Key

Retrieve the IP blacklist in various formats. Supports filtering by confidence level, source, and category. Ideal for firewall integration and automated blocking. Does not count against any daily quota — tier-gated feature (Contributor and up).

Parameters

Name Type Required Default Description
format string No json Response format: json, txt, or csv
source string No community Blacklist source: community (default) — only one source available; the source parameter is reserved for future use
confidence_minimum integer No 75 Minimum abuse confidence percentage (0-100)
category integer No Filter by threat category ID
limit integer No 10000 Maximum number of entries to return

Examples

curl
# JSON format
curl -H "X-Key: YOUR_API_KEY" \
     "https://reportedip.de/wp-json/reportedip/v2/blacklist?confidence_minimum=90"

# Plain text (one IP per line, for firewall rules)
curl -H "X-Key: YOUR_API_KEY" \
     "https://reportedip.de/wp-json/reportedip/v2/blacklist?format=txt&source=all"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist?confidence_minimum=90',
    array(
        'headers' => array(
            'X-Key' => 'YOUR_API_KEY',
        ),
    )
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist',
    params={
        'confidence_minimum': 90,
        'source': 'all'
    },
    headers={'X-Key': 'YOUR_API_KEY'}
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist?confidence_minimum=90',
    {
        headers: { 'X-Key': 'YOUR_API_KEY' }
    }
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "generatedAt": "2026-03-09T15:00:00Z",
    "count": 4821,
    "confidenceMinimum": 90,
    "entries": [
      {
        "ip": "1.2.3.4",
        "abuseConfidencePercentage": 100,
        "totalReports": 156,
        "lastReportedAt": "2026-03-09T14:22:31Z",
        "categories": [18, 21, 22]
      },
      {
        "ip": "5.6.7.8",
        "abuseConfidencePercentage": 95,
        "totalReports": 87,
        "lastReportedAt": "2026-03-09T13:45:12Z",
        "categories": [15, 18]
      }
    ]
  }
}
GET /blacklist-categories
Public

Retrieve all available blacklist categories used for classifying entries. Does not count against any daily quota.

Examples

curl
curl "https://reportedip.de/wp-json/reportedip/v2/blacklist-categories"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist-categories'
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist-categories'
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist-categories'
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": [
    {
      "id": 1,
      "name": "Botnet",
      "slug": "botnet",
      "description": "Known botnet command and control or participant"
    },
    {
      "id": 2,
      "name": "Brute-Force",
      "slug": "brute-force",
      "description": "Credential brute-force attacks"
    },
    {
      "id": 3,
      "name": "Spam",
      "slug": "spam",
      "description": "Spam sources"
    }
  ]
}
GET /blacklist-stats
Public

Retrieve statistics about the blacklist including total counts and distribution by confidence level and category. Does not count against any daily quota.

Examples

curl
curl "https://reportedip.de/wp-json/reportedip/v2/blacklist-stats"
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist-stats'
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist-stats'
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/blacklist-stats'
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "total": 12483,
    "community": 12483,
    "byConfidence": {
      "90-100": 4821,
      "75-89": 3247,
      "50-74": 2891,
      "25-49": 1524
    },
    "byCategory": [
      {"name": "Brute-Force", "count": 5432},
      {"name": "Web App Attack", "count": 3218},
      {"name": "SSH", "count": 2847},
      {"name": "Port Scan", "count": 986}
    ]
  }
}

Advanced Endpoints

Advanced endpoints for power users. Require Professional or Enterprise tier API keys.

GET /reports/{ip}
Professional+

Retrieve all individual reports for a specific IP address. Returns paginated report details including reporter info, categories, and timestamps. Does not count against any daily quota — tier-gated feature (Professional and up).

Parameters

Name Type Required Default Description
ip string Yes IPv4 or IPv6 address (in URL path)
page integer No 1 Page number for pagination
per_page integer No 25 Reports per page

Examples

curl
curl -H "X-Key: YOUR_API_KEY" \
     "https://reportedip.de/wp-json/reportedip/v2/reports/1.2.3.4?page=1&per_page=25"
php
$ip = '1.2.3.4';
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/reports/' . $ip . '?page=1',
    array(
        'headers' => array(
            'X-Key' => 'YOUR_API_KEY',
        ),
    )
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

ip = '1.2.3.4'
response = requests.get(
    f'https://reportedip.de/wp-json/reportedip/v2/reports/{ip}',
    params={'page': 1, 'per_page': 25},
    headers={'X-Key': 'YOUR_API_KEY'}
)
data = response.json()
javascript
const ip = '1.2.3.4';
const response = await fetch(
    `https://reportedip.de/wp-json/reportedip/v2/reports/${ip}?page=1&per_page=25`,
    {
        headers: { 'X-Key': 'YOUR_API_KEY' }
    }
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "ip": "1.2.3.4",
    "reports": [
      {
        "id": 58234,
        "categories": [18, 21],
        "comment": "SSH brute force with 500+ attempts",
        "reportedAt": "2026-03-09T14:22:31Z",
        "reporterRole": "honeypot",
        "aggregationCount": 12
      },
      {
        "id": 58102,
        "categories": [22],
        "comment": "Port scanning on TCP 22, 80, 443, 8080",
        "reportedAt": "2026-03-09T10:15:00Z",
        "reporterRole": "contributor",
        "aggregationCount": 0
      }
    ],
    "total": 42,
    "page": 1,
    "per_page": 25,
    "total_pages": 2
  }
}
POST /bulk-check
Professional+

Check the reputation of multiple IP addresses in a single request. Accepts up to 1,000 IPs per request. Charges +N against your daily check quota where N is the number of valid IPs in the request. If the call would exceed the remaining quota the server returns HTTP 429 and the counter is not incremented.

Parameters

Name Type Required Default Description
ips array Yes Array of IPv4/IPv6 addresses (max 1,000)

Examples

curl
curl -X POST \
     -H "X-Key: YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"ips": ["1.2.3.4", "5.6.7.8", "9.10.11.12"]}' \
     "https://reportedip.de/wp-json/reportedip/v2/bulk-check"
php
$response = wp_remote_post(
    'https://reportedip.de/wp-json/reportedip/v2/bulk-check',
    array(
        'headers' => array(
            'X-Key'        => 'YOUR_API_KEY',
            'Content-Type' => 'application/json',
        ),
        'body' => wp_json_encode(array(
            'ips' => array('1.2.3.4', '5.6.7.8', '9.10.11.12'),
        )),
    )
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

response = requests.post(
    'https://reportedip.de/wp-json/reportedip/v2/bulk-check',
    json={
        'ips': ['1.2.3.4', '5.6.7.8', '9.10.11.12']
    },
    headers={'X-Key': 'YOUR_API_KEY'}
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/bulk-check',
    {
        method: 'POST',
        headers: {
            'X-Key': 'YOUR_API_KEY',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            ips: ['1.2.3.4', '5.6.7.8', '9.10.11.12']
        })
    }
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "OK"
  },
  "data": {
    "results": [
      {
        "ip": "1.2.3.4",
        "abuseConfidencePercentage": 87,
        "totalReports": 42,
        "lastReportedAt": "2026-03-09T14:22:31Z",
        "categories": [18, 21, 22]
      },
      {
        "ip": "5.6.7.8",
        "abuseConfidencePercentage": 0,
        "totalReports": 0,
        "lastReportedAt": null,
        "categories": []
      },
      {
        "ip": "9.10.11.12",
        "abuseConfidencePercentage": 45,
        "totalReports": 3,
        "lastReportedAt": "2026-03-07T09:30:00Z",
        "categories": [15]
      }
    ],
    "checked": 3
  }
}
POST /bulk-report
Enterprise

Submit multiple IP reports in a single request using CSV-formatted data. Designed for automated systems and honeypots that need to report large volumes of malicious activity. Charges +N against your daily report quota where N is the number of submitted reports. Never counts against the check quota.

Parameters

Name Type Required Default Description
csv string Yes CSV data with columns: IP, Categories, Comment (one report per line)

Examples

curl
curl -X POST \
     -H "X-Key: YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"csv": "1.2.3.4,18|21,SSH brute force\n5.6.7.8,22,Port scanning\n9.10.11.12,15|18,Distributed attack"}' \
     "https://reportedip.de/wp-json/reportedip/v2/bulk-report"
php
$csv = "1.2.3.4,18|21,SSH brute force\n";
$csv .= "5.6.7.8,22,Port scanning\n";
$csv .= "9.10.11.12,15|18,Distributed attack";

$response = wp_remote_post(
    'https://reportedip.de/wp-json/reportedip/v2/bulk-report',
    array(
        'headers' => array(
            'X-Key'        => 'YOUR_API_KEY',
            'Content-Type' => 'application/json',
        ),
        'body' => wp_json_encode(array(
            'csv' => $csv,
        )),
    )
);
$data = json_decode(wp_remote_retrieve_body($response), true);
python
import requests

csv_data = """1.2.3.4,18|21,SSH brute force
5.6.7.8,22,Port scanning
9.10.11.12,15|18,Distributed attack"""

response = requests.post(
    'https://reportedip.de/wp-json/reportedip/v2/bulk-report',
    json={'csv': csv_data},
    headers={'X-Key': 'YOUR_API_KEY'}
)
data = response.json()
javascript
const csvData = [
    '1.2.3.4,18|21,SSH brute force',
    '5.6.7.8,22,Port scanning',
    '9.10.11.12,15|18,Distributed attack'
].join('\n');

const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/bulk-report',
    {
        method: 'POST',
        headers: {
            'X-Key': 'YOUR_API_KEY',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ csv: csvData })
    }
);
const data = await response.json();

Response

200 OK
json
{
  "meta": {
    "success": true,
    "code": 200,
    "message": "Bulk report processed"
  },
  "data": {
    "success_count": 3,
    "error_count": 0,
    "errors": []
  }
}

2FA Relay Endpoints

Managed 2FA delivery for the ReportedIP Hive WordPress plugin. PRO+ tiers may queue authentication mails and SMS through this relay; the service consumes the monthly inclusive quota first and falls back to the prepaid bundle balance once the inclusive cap is reached.

Inclusive monthly quota: Free / Contributor not eligible · Professional 500 mails · 25 SMS · Business 2,500 mails · 75 SMS · Enterprise fair-use unlimited. PRO and Business may top up via prepaid bundles (hive_mail_bundle_1000/5000/25000, hive_sms_bundle_50/200/500).
Refund protection — bundle_balance is signed: a Stripe refund (charge.refunded) on a previously consumed bundle reduces the saldo and may push it below zero. While the saldo is non-positive and the inclusive quota is exhausted, sends fail with HTTP 402 cap_reached_buy_bundle until a fresh bundle is purchased.
GET /relay-quota
PRO / Business / Enterprise

Returns the inclusive monthly quota plus the prepaid bundle balance for both Mail and SMS relay. Used by the Hive plugin dashboard to render usage bars and bundle hints.

Examples

curl
curl -H 'X-Key: YOUR_API_KEY' \
     https://reportedip.de/wp-json/reportedip/v2/relay-quota
php
$response = wp_remote_get(
    'https://reportedip.de/wp-json/reportedip/v2/relay-quota',
    array( 'headers' => array( 'X-Key' => 'YOUR_API_KEY' ) )
);
$data = json_decode( wp_remote_retrieve_body( $response ), true );
python
import requests

response = requests.get(
    'https://reportedip.de/wp-json/reportedip/v2/relay-quota',
    headers={'X-Key': 'YOUR_API_KEY'}
)
data = response.json()
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/relay-quota',
    { headers: { 'X-Key': 'YOUR_API_KEY' } }
);
const data = await response.json();

Response

200 OK
json
{
  "tier": "professional",
  "role": "reportedip_professional",
  "mail": {
    "sent": 18,
    "queued": 0,
    "queued_total": 18,
    "failed": 0,
    "limit": 500,
    "inclusive_limit": 500,
    "inclusive_used": 18,
    "inclusive_available": 482,
    "bundle_balance": 1000,
    "bundle_eligible": true,
    "period_start": "2026-05-01T00:00:00Z",
    "period_end":   "2026-05-31T23:59:59Z"
  },
  "sms": {
    "sent": 3,
    "queued": 0,
    "queued_total": 3,
    "failed": 0,
    "limit": 25,
    "inclusive_limit": 25,
    "inclusive_used": 3,
    "inclusive_available": 22,
    "bundle_balance": 50,
    "bundle_eligible": true,
    "period_start": "2026-05-01T00:00:00Z",
    "period_end":   "2026-05-31T23:59:59Z"
  },
  "mail_bundle_balance": 1000,
  "sms_bundle_balance":  50
}
POST /relay-mail
PRO / Business / Enterprise

Queues a transactional 2FA mail through the SPF/DKIM/DMARC-verified relay. Consumes one slot from the inclusive monthly mail quota; once exhausted, one credit from `mail_bundle_balance`. Returns HTTP 402 when both are empty.

Parameters

Name Type Required Default Description
to string Yes Recipient email address
subject string Yes Mail subject line
html_body string Yes HTML body of the mail
plain_body string No Optional plain-text fallback body
site_url string No Origin site URL (used for per-site daily caps and audit logs)

Examples

curl
curl -X POST \
     -H 'X-Key: YOUR_API_KEY' \
     -H 'Content-Type: application/json' \
     -d '{"to":"[email protected]","subject":"Your 2FA code","html_body":"<p>Code: 123456</p>"}' \
     https://reportedip.de/wp-json/reportedip/v2/relay-mail
php
$response = wp_remote_post(
    'https://reportedip.de/wp-json/reportedip/v2/relay-mail',
    array(
        'headers' => array( 'X-Key' => 'YOUR_API_KEY', 'Content-Type' => 'application/json' ),
        'body'    => wp_json_encode( array(
            'to'        => '[email protected]',
            'subject'   => 'Your 2FA code',
            'html_body' => '<p>Code: 123456</p>',
        ) ),
    )
);
python
import requests

response = requests.post(
    'https://reportedip.de/wp-json/reportedip/v2/relay-mail',
    headers={'X-Key': 'YOUR_API_KEY'},
    json={
        'to': '[email protected]',
        'subject': 'Your 2FA code',
        'html_body': '<p>Code: 123456</p>',
    },
)
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/relay-mail',
    {
        method: 'POST',
        headers: { 'X-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
        body: JSON.stringify({
            to: '[email protected]',
            subject: 'Your 2FA code',
            html_body: '<p>Code: 123456</p>',
        }),
    }
);

Response

200 OK
json
{
  "ok": true,
  "queue_id": 48217,
  "remaining_quota": {
    "sent": 18,
    "queued": 1,
    "queued_total": 19,
    "failed": 0,
    "limit": 500,
    "inclusive_limit": 500,
    "inclusive_used": 19,
    "inclusive_available": 481,
    "bundle_balance": 1000,
    "bundle_eligible": true,
    "period_start": "2026-05-01T00:00:00Z",
    "period_end":   "2026-05-31T23:59:59Z"
  }
}
POST /relay-sms
PRO / Business / Enterprise

Queues a 2FA SMS via the managed worldwide relay. The body is server-side rendered from a registered template (e.g. <code>2fa_login</code>) so the actual code never appears in client logs. HTTP 402 when both the inclusive quota and the prepaid bundle are exhausted; HTTP 422 with code <code>country_not_supported</code> when the destination country is unavailable for cost or operational reasons; HTTP 429 when the recipient or per-site daily anti-fraud cap is hit.

Parameters

Name Type Required Default Description
to string Yes Recipient phone in E.164 format (e.g. +49170...)
template_code string Yes Server-side template id, e.g. <code>2fa_login</code>
vars object Yes Template variables: <code>{ code, expiry_min, lang? }</code>
site_url string No Origin site URL (used for per-site daily caps and audit logs)

Examples

curl
curl -X POST \
     -H 'X-Key: YOUR_API_KEY' \
     -H 'Content-Type: application/json' \
     -d '{"to":"+491701234567","template_code":"2fa_login","vars":{"code":"123456","expiry_min":5,"lang":"de"}}' \
     https://reportedip.de/wp-json/reportedip/v2/relay-sms
php
$response = wp_remote_post(
    'https://reportedip.de/wp-json/reportedip/v2/relay-sms',
    array(
        'headers' => array( 'X-Key' => 'YOUR_API_KEY', 'Content-Type' => 'application/json' ),
        'body'    => wp_json_encode( array(
            'to'            => '+491701234567',
            'template_code' => '2fa_login',
            'vars'          => array( 'code' => '123456', 'expiry_min' => 5, 'lang' => 'de' ),
        ) ),
    )
);
python
import requests

response = requests.post(
    'https://reportedip.de/wp-json/reportedip/v2/relay-sms',
    headers={'X-Key': 'YOUR_API_KEY'},
    json={
        'to': '+491701234567',
        'template_code': '2fa_login',
        'vars': {'code': '123456', 'expiry_min': 5, 'lang': 'de'},
    },
)
javascript
const response = await fetch(
    'https://reportedip.de/wp-json/reportedip/v2/relay-sms',
    {
        method: 'POST',
        headers: { 'X-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
        body: JSON.stringify({
            to: '+491701234567',
            template_code: '2fa_login',
            vars: { code: '123456', expiry_min: 5, lang: 'de' },
        }),
    }
);

Response

200 OK
json
{
  "ok": true,
  "queue_id": 901,
  "remaining_quota": {
    "sent": 3,
    "queued": 1,
    "queued_total": 4,
    "failed": 0,
    "limit": 25,
    "inclusive_limit": 25,
    "inclusive_used": 4,
    "inclusive_available": 21,
    "bundle_balance": 50,
    "bundle_eligible": true,
    "period_start": "2026-05-01T00:00:00Z",
    "period_end":   "2026-05-31T23:59:59Z"
  }
}

Error responses for relay endpoints

StatusCodeMeaning
401missing_api_key / invalid_api_keyThe X-Key header is missing, malformed, or refers to a deactivated key.
403tier_forbiddenThe caller's tier (Free / Contributor) is not eligible for relay delivery.
402cap_reached_buy_bundleInclusive monthly cap reached and the prepaid bundle balance is empty or negative after a refund. Buy a bundle in the dashboard to resume.
402monthly_cap_reachedInclusive monthly cap reached on a tier without bundle eligibility.
429recipient_backoff / site_daily_capAnti-fraud throttle. The retry-after header indicates how long to wait.

Deprecated Endpoints

These endpoints are deprecated and will be removed in a future version. Please migrate to the recommended alternatives.

GET /blacklist-detailed
API Key
Deprecated. Use GET /blacklist instead.

Previously returned a detailed blacklist. Kept alive for backward compatibility with older Hive installations. Does not count against any daily quota (since v2.5.1 — was counted as a check before).

GET /blacklist-combined
API Key
Deprecated. Use GET /blacklist?source=all instead.

Previously returned a combined blacklist from all sources. Kept alive for backward compatibility with older Hive installations. Does not count against any daily quota (since v2.5.1).

GET /blacklist-export/git
API Key
Deprecated. Use GET /blacklist?format=txt instead.

Previously exported the blacklist in plain text format for Git repository integration. Kept alive for backward compatibility. Does not count against any daily quota (since v2.5.1).

Security Focused
GDPR Compliant
Made in Germany
Back to Docs