v1 Lädt…

API-Referenz

Integrieren Sie unsichtbare Bot- & Proxy-Erkennung in Ihr Produkt. Keine CAPTCHAs. Keine Reibung. Unter 150 ms serverseitig pro Auswertung.

Zuletzt aktualisiert im August 2026 · jede API-Änderung landet im Changelog · Stabilitätsrichtlinie: nur additive Änderungen

Playbooks je Angriff: Kontoübernahme, Card Testing, Bonusmissbrauch, und mehr →

Schnellstart

Von null zur funktionierenden Integration in 5 Minuten. Erstellen Sie einen kostenlosen Schlüssel unter /signup — 1.000 Anfragen/Stunde, keine Karte.

Node.js-SDK npm install @sentinelsup/sdk npm ↗ · GitHub ↗
Python-SDK pip install sentinelsup PyPI ↗ · GitHub ↗
OpenAPI 3.1 https://maskbreak.com/openapi.json Spec ↗ ·
Mit KI einrichten Claude Code · Cursor · Copilot · Windsurf

Sie nutzen einen KI-Coding-Assistenten? Fügen Sie diesen Prompt ein, und er baut Maskbreak Ende-zu-Ende in Ihre App ein — Frontend-Script, Backend-Prüfung, Umgebungsvariable und ein Test. Er folgt der maschinenlesbaren Anleitung unter maskbreak.com/integrate.md.

Fetch https://maskbreak.com/integrate.md and follow it to add Maskbreak fraud protection to this app — protect signup, login, and checkout. My API key is sk_live_YOUR_API_KEY; put it in a SENTINEL_KEY env var, never in client-side code. Then show me how to test it.
Ihr Maskbreak-API-Endpunkt
Lädt…
Ihr Backend ruft diese URL auf. Ihr API-Schlüssel authentifiziert die Anfrage.
Vollständiges Integrationsbeispiel
// ——— STEP 1: Add SDK to your HTML <head> —————————————————————————————————————
<script async src="loading..."></script>
<form class="monocle-enriched" id="login-form">
  <input type="email" name="email" />
  <!-- SDK auto-injects BOTH: name="monocle" (network) + name="sentinel_fp" (device) -->
</form>

// ——— STEP 2: Read both tokens in your frontend JS ——————————————————————————————
document.getElementById('login-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const email = e.target.email.value;
  // Sentinel.collect() waits for the device layer, then returns both.
  const { token, fingerprintEventId } = await window.Sentinel.collect();
  // Send to YOUR backend (never call Maskbreak directly from the browser)
  await fetch('your-login-endpoint', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, token, fingerprintEventId })
  });
});

// ——— STEP 3: Evaluate on your backend (Node.js) ——————————————————————————————
app.post('/your-login-endpoint', async (req, res) => {
  const { email, token, fingerprintEventId } = req.body;

  const result = await fetch('https://maskbreak.com/v1/evaluate', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    // Both layers — network + device — in one call.
    body: JSON.stringify({ token, fingerprintEventId })
  });

  const data = await result.json();

  if (data.decision === 'block') {
    return res.status(403).json({ error: 'Bot or proxy detected.' });
  }
  if (data.decision === 'review') {
    // e.g. require email verification or step-up auth
  }

  // ✓ Connection is clean — proceed
  res.json({ success: true });
});

Live ausprobieren

Rufen Sie den Sandbox-Endpunkt mit einem Klick auf. Keine Registrierung, kein API-Schlüssel — nur echte /v1/evaluate-Antwortstrukturen, die Sie in Ihren Code übernehmen können.

Anfrage
GET https://maskbreak.com/v1/evaluate/sample
   ?scenario=clean
Keine Authentifizierung nötig · 30 Anfragen/Min · liefert Beispieldaten
Antwort
wartet auf Ausführung…
{
  "click ▶ Run Request": "to see live JSON"
}

Produktionsaufrufe nutzen POST /v1/evaluate mit einem token aus dem SDK und einem Authorization: Bearer sk_live_...-Header. Der Beispiel-Endpunkt liefert dieselbe Antwortstruktur, sodass Sie Ihre Parsing-Logik vor der Registrierung verdrahten können.

Eine echte IP nachschlagen
echtes Pipeline-Urteil · kein Schlüssel · ratenlimitiert — ein paar Versuche pro Minute
Anfrage
POST https://maskbreak.com/api/lookup
{ "ip": "185.220.101.34" }
Echtes Urteil aus der Live-Pipeline (ein Tor-Exit ist vorausgefüllt). Streng ratenlimitiert — ein paar Versuche pro Minute; für Volumen nutzen Sie GET /v1/lookup mit einem Schlüssel.
Antwort
wartet auf Ausführung…
{
  "click ▶ Run Lookup": "for a live verdict on this IP"
}

So funktioniert es

Maskbreak nutzt einen dreistufigen Ablauf Client → Ihr Backend → Maskbreak-API, damit Ihr geheimer Schlüssel nie im Browser landet.

1
Erfassung im Browser

Das Maskbreak-SDK läuft unsichtbar im Browser Ihres Nutzers und sammelt Telemetrie. Es fügt Ihren Formularen ein verschlüsseltes token hinzu.

2
Token weitergeleitet

Ihr Frontend sendet das Token zusammen mit den übrigen Formulardaten an Ihren eigenen Backend-Server.

3
API-Auswertung

Ihr Backend ruft POST /v1/evaluate mit Ihrem geheimen Schlüssel auf. Maskbreak liefert sofort einen Threat-Intelligence-Bericht.

Authentifizierung

Alle Anfragen an /v1/evaluate müssen Ihren geheimen API-Schlüssel als Bearer-Token enthalten. Ihren Schlüssel finden Sie im Dashboard.

Authorization: Bearer sk_live_YOUR_SECRET_KEY
Halten Sie Ihren Schlüssel geheim
Schreiben Sie sk_live_… niemals in Ihr HTML, JavaScript oder anderen clientseitigen Code. Verwenden Sie ihn nur in Ihrer Backend-Serverumgebung.

Schlüssel rotieren

Rotieren Sie in der Konsole (Integration → Rotieren, oder Einstellungen → API-Schlüssel; Ihr Passwort wird erneut abgefragt). Der neue Schlüssel funktioniert sofort, und der bisherige bleibt 24 Stunden gültig, damit ein Deployment ohne Lücke umstellen kann. Ist ein Schlüssel geleakt, beendet Alten Schlüssel jetzt widerrufen in den Einstellungen diese Frist sofort. Während der Frist beantwortet jeder Schlüssel /v1/usage mit seinem eigenen Stundenkontingent.

Zwei weitere Schlüssel gehören zu jedem Konto: ein persönlicher sk_test_…-Schlüssel, der die volle Pipeline ausführt, ohne zu zählen, zu speichern oder zu alarmieren (eigenes Stundenkontingent, von der IP-Allowlist ausgenommen), und der öffentliche sk_test_sandbox-Schlüssel, der ganz ohne Konto nur die deterministischen Test-Token beantwortet. Eine optionale IP-Allowlist (Einstellungen → API-Schlüssel-Sicherheit) beschränkt den Live-Schlüssel auf Ihre Serveradressen; Aufrufe von anderswo erhalten 403 mit der betreffenden Adresse im Hinweis.

OAuth 2.0 Client Credentials Neu

Tauschen Sie Ihre Konto-E-Mail und Ihren API-Schlüssel über den Standard-Grant client_credentials gegen ein kurzlebiges Bearer-Token. Das Token trägt Ihre Konto-ID, nie den Schlüssel selbst. Es gilt 60 Minuten und funktioniert über eine Schlüsselrotation hinweg (es löst auf den jeweils aktuellen Schlüssel auf), sodass eine Rotation bereits ausgestellte Token nicht widerruft — stellen Sie keine neuen mehr aus und lassen Sie die alten ablaufen. Ein mit Ihrem sk_test_-Schlüssel geprägtes Token bleibt ein Test-Credential. API-Schlüssel funktionieren genau wie zuvor; das hier ist additiv.

OAuth-Token-Endpunkt
POST /oauth/token
Tauscht E-Mail + API-Schlüssel gegen ein Bearer-Token. Discovery-Metadaten unter /.well-known/oauth-authorization-server und /.well-known/oauth-protected-resource.
cURL
curl -X POST https://maskbreak.com/oauth/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"client_credentials","client_id":"your@email.com","client_secret":"sk_live_..."}'

Verwenden Sie das zurückgegebene access_token überall dort im Authorization: Bearer-Header, wo ein API-Schlüssel akzeptiert wird. Token laufen ab; erneuern Sie sie durch Wiederholen des Austauschs. Der Schlüssel selbst verlässt Ihren Server nie.

1

SDK einbinden

Binden Sie das Maskbreak-SDK auf jeder Seite ein, auf der Sie Nutzer auswerten wollen. Ein Script lädt beide Erkennungsschichten — Netzwerkintelligenz (VPN, Proxy, Rechenzentrum) und Geräteintelligenz (Antidetect-Browser, Bots, Manipulation) — und fügt beide Token in Ihre Formulare ein.

HTML — in <head> einfügen
<!-- Maskbreak SDK — network + device, paste inside <head> -->
<script async src="loading..."></script>

<!-- Add class="monocle-enriched" to any form you want evaluated -->
<form class="monocle-enriched" id="my-form">
  <!-- The SDK injects both automatically: -->
  <input type="hidden" name="monocle"    value="eyJ..." /> // network
  <input type="hidden" name="sentinel_fp" value="a1b2..." /> // device
</form>

Das SDK braucht etwa 1–2 Sekunden zum Laden und Erzeugen der Token. Wenn die Geräteschicht nicht laufen kann (z. B. weil ein gehärteter Browser sie blockiert), läuft die Auswertung allein über die Netzwerkschicht weiter.

2

Token einsammeln

Rufen Sie beim Absenden Sentinel.collect() auf — es wartet, bis sich die Geräteschicht gesetzt hat, und liefert { token, fingerprintEventId }. Leiten Sie beides an Ihr Backend weiter. (Oder lesen Sie die versteckten Felder monocle und sentinel_fp direkt aus.)

JavaScript (Frontend)
document.getElementById('my-form').addEventListener('submit', async (e) => {
  e.preventDefault();

  // Both layers: network token + device event id
  const { token, fingerprintEventId } = await window.Sentinel.collect();

  if (!token) {
    // Network SDK still loading — ask user to try again
    return showError('Security check loading. Please try again.');
  }

  // Forward both to your backend with the rest of the form data
  const res = await fetch('/your-backend-endpoint', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      email: e.target.email.value,
      token, fingerprintEventId  // ← both layers to your backend
    })
  });
});
3

Den Evaluate-Endpunkt aufrufen

POST lädt…

Rufen Sie das von Ihrem Backend-Server auf — nie aus dem Browser. Übergeben Sie das Token vom Client und Ihren geheimen API-Schlüssel.

Request-Body

token string erforderlich
Das verschlüsselte Token aus dem Feld input[name="monocle"] des Clients.
fingerprintEventId string
Die Event-ID der Geräteintelligenz — das SDK erfasst sie und fügt sie als sentinel_fp ein; leiten Sie sie hier weiter (beide Namen werden akzeptiert), um die device.*-Signale freizuschalten (Antidetect, Automatisierung, Emulator, …). Ohne sie erhalten Sie ein reines Netzwerk-Urteil.
accountId string
Optional: Ihre eigene Konto-/Nutzer-ID für diese Sitzung. Zusammen mit fingerprintEventId zählt Maskbreak, mit wie vielen verschiedenen Konten dieses Gerät unter Ihrem API-Schlüssel verknüpft wurde, und liefert device.linked_accounts / device.multi_account — Multi-Accounting-Erkennung ohne zusätzliche Integration. Nur als Einweg-Hash gespeichert.
email string
Optional: die E-Mail-Adresse, mit der sich der Besucher registriert. Fügt der Antwort email.disposable hinzu — geprüft gegen einen laufend aktualisierten Feed mit Tausenden Wegwerf-Domains. Ein Treffer fügt den Grund disposable_email hinzu, erhöht den risk_score und stuft allow zu review hoch. Die Adresse wird nur vorübergehend geprüft und nie gespeichert oder protokolliert.
tz string
Optional: die IANA-Zeitzone des Besuchers, z. B. Europe/Tallinn. Unser Client-SDK sendet sie automatisch als sentinel_tz, was dieser Endpunkt ebenfalls akzeptiert; selbst auslesen können Sie sie mit Intl.DateTimeFormat().resolvedOptions().timeZone — ohne Berechtigungsabfrage und ohne Geolokalisierung. Fügt der Antwort einen timezone-Block hinzu. Sieht die Verbindung gewöhnlich aus, während die Uhr des Browsers zu einem anderen Land gehört, ist das die Form eines Residential-Proxys, den die Netzwerkschicht nicht erwischt hat: es fügt den Grund timezone_mismatch hinzu, erhöht den risk_score und stuft allow zu review hoch. Bewusst nicht ausgelöst bei VPN, Proxy, Tor oder Rechenzentrums-Exit — der Uhr zu widersprechen ist genau das, was die tun — und nie allein genug für block, weil Reisende und Auswanderer hier legitim landen.

Testen ohne Browser: Senden Sie ein deterministisches Test-Token — test_clean, test_vpn, test_proxy, test_datacenter oder test_tor —, um Ihre allow-/review-/block-Behandlung Ende-zu-Ende zu prüfen. Testaufrufe werden wie echte authentifiziert und ratenlimitiert, aber nie berechnet, gespeichert oder per Webhook gemeldet, und die Antwort trägt "test": true.

CI & Staging ohne Konto: Der öffentliche Sandbox-Schlüssel sk_test_sandbox akzeptiert dieselben test_*-Token und liefert dieselben deterministischen Strukturen — keine Registrierung, nichts berechnet, nichts gespeichert, berührt nie eine echte Quote. Er beantwortet nur Test-Token (Live-Traffic braucht weiterhin Ihren echten Schlüssel) und ist pro IP ratenlimitiert. curl -X POST https://maskbreak.com/v1/evaluate -H "Authorization: Bearer sk_test_sandbox" -H "Content-Type: application/json" -d '{"token":"test_vpn"}'

Ihr eigener Testschlüssel (volle Pipeline, kein Fußabdruck): Jedes Konto hat zusätzlich einen persönlichen sk_test_…-Schlüssel (Einstellungen → API-Schlüssel), der anders als die Sandbox die komplette Live-Pipeline ausführt — echte Token, echte Geräteintelligenz, Ihre Regeln und Ausnahme-Pins eingeschlossen. Die Events, die er erzeugt, sind in der Konsole als Test markiert, aus Verbrauch und Statistik ausgenommen, lösen nie Webhooks oder Limit-E-Mails aus, und die Antwort trägt "test": true. Er hat sein eigenes Stundenkontingent und ist bewusst von der IP-Allowlist ausgenommen, damit CI und Laptops die Pipeline ausprobieren können, ohne Löcher in Ihre Produktionsbeschränkung zu schlagen.

const response = await fetch('https://maskbreak.com/v1/evaluate', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    token: req.body.token   // as sent by your frontend (see Quick Start Step 2)
  })
});

const data = await response.json();
// data.decision → 'allow' | 'review' | 'block' (covers VPN, proxy,
// datacenter, Tor, antidetect, automation) — route on this
// data.reasons  → machine-readable why

if (data.decision === 'block') {
  return res.status(403).json({ error: 'Suspicious connection.' });
}
# pip install sentinelsup
from sentinel import Sentinel

s = Sentinel(api_key='sk_live_YOUR_API_KEY')  # or omit — reads SENTINEL_KEY env var

result = s.evaluate(token=sentinel_token)  # from the form POST body

# result.decision → 'allow' | 'review' | 'block' — route on this
# result.reasons  → machine-readable why

if result.is_blocked:
    return '403 Suspicious connection', 403
curl -X POST 'https://maskbreak.com/v1/evaluate' \
  -H 'Authorization: Bearer sk_live_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"token": "eyJ..."}'
// composer require sentinelsup/sdk
$sentinel = new \Sentinel\Client();  // or pass the key — reads SENTINEL_KEY env var

$result = $sentinel->evaluate([
    'token' => $_POST['monocle'],  // hidden input the client SDK adds
]);

// $result->decision → 'allow' | 'review' | 'block' — route on this
// $result->reasons  → machine-readable why

if ($result->isBlocked()) {
    http_response_code(403);
    exit();
}

Antwortobjekt

Ein erfolgreicher Aufruf liefert 200 OK mit dieser JSON-Struktur.

Feld Typ Beschreibung
decision string Empfohlene Aktion: "allow", "review" oder "block". Nur beratend — die Richtlinie legen Sie fest. Das reasons-Array erklärt jede Entscheidung, sodass Sie sie protokollieren oder Ihrem Endnutzer einen Ablehnungsgrund zeigen können. Wenn Sie in Ihrem Dashboard eigene Regeln konfigurieren, liefert dieses Feld Ihre Aktion für ein passendes Signal (die strengste Regel gewinnt).
engine_decision string decision_source wird immer dann zurückgegeben, wenn Ihre Richtlinie auf dieses Event gepasst hat: "rules" (mit rule_matched, das die Signale nennt, die eine Regel ausgelöst haben) oder "exception" (mit exception_matched, das den IP-/Besucher-Pin aus der Ausnahmenliste Ihres Dashboards nennt — explizite Pins schlagen Signalregeln). engine_decision erscheint zusätzlich, wenn der Treffer die Entscheidung tatsächlich verändert hat, und bewahrt das eigene Risiko-Score-Urteil der Engine.
risk_score integer Zusammengesetzter Risiko-Score 0–100 über alle Netzwerk- und Gerätesignale. Wird von eigenen Regeln nicht verändert.
isSuspicious boolean Legacy-Komfortflag. true, wenn VPN, Proxy, Antidetect, Automatisierung oder Emulator ausgelöst haben. Tor- und Rechenzentrumssignale erhöhen den risk_score und steuern decision (Tor blockiert), setzen dieses Flag aber nicht — routen Sie für volle Abdeckung über decision.
ip string Die entlarvte, echte IP-Adresse des Nutzers. Gespiegelt unter details.ip.
country string ISO-3166-1-Ländercode (z. B. "US", "EE"). Gespiegelt unter details.cc.
network.vpn boolean Kommerzielles VPN erkannt (NordVPN, Proton, ExpressVPN usw.). Gespiegelt unter details.vpn.
network.proxy boolean Residential- oder SOCKS/HTTP-Proxy erkannt. Gespiegelt unter details.proxied.
network.datacenter boolean Traffic aus einem bekannten Rechenzentrums-/Cloud-Anbieter-ASN. Gespiegelt unter details.dch.
network.tor boolean Tor-Exit-Node erkannt. Gespiegelt unter details.tor.
network.anonymous boolean Irgendeine Anonymisierungsschicht erkannt. Gespiegelt unter details.anon.
network.residential boolean true, wenn weder Rechenzentrum noch Proxy ausgelöst haben (sieht nach einer echten Heim-IP aus).
network.service string Identifizierter Anbieter, wenn bekannt (z. B. "PROTON_VPN", "BRIGHT_DATA"). Gespiegelt unter details.service.
device.antidetect boolean Antidetect-/Fingerprint-Spoofing-Browser (Multilogin, Kameleo, GoLogin usw.). Nur vorhanden, wenn fingerprintEventId gesendet wurde.
device.automation boolean Automatisierter Browser erkannt (Puppeteer, Playwright, Selenium).
device.emulator boolean Mobil-Emulator.
device.virtual_machine boolean Virtuelle Maschine.
device.incognito boolean Privater / Inkognito-Modus erkannt.
device.privacy_mode boolean Erweiterte Datenschutzeinstellungen aktiv (z. B. Brave Shields, Firefox resist-fingerprinting).
device.ip_blocklisted boolean Die Besucher-IP steht auf E-Mail-Spam- oder Angriffsquellen-Blocklisten.
device.high_activity boolean Dieses Gerät wird ungewöhnlich oft identifiziert (High-Activity Device). Informativ — häufige Besuche allein sind kein Betrug, aber in Kombination mit anderen Signalen deuten sie oft auf Automatisierung oder Farming hin. Fügt den Grundcode high_activity_device hinzu.
device.visitor_id string Stabiler Geräte-Fingerprint-Hash. Dasselbe Gerät liefert über Sitzungen hinweg dieselbe ID, auch nach dem Löschen der Cookies — nützlich für ATO-Abwehr und Geräte-Clustering.
device.tampering_score number Manipulations-Score 0–1. Über 0,6 deutet stark auf einen Antidetect-Browser hin; 0,3–0,6 bedeutet weiche Inkonsistenzen; unter 0,3 ist normal.
device.times_seen integer Wie oft Maskbreak dieses Gerät in den letzten 90 Tagen gesehen hat, geschlüsselt über einen Einweg-Hash der Besucher-ID (die rohe ID wird nie gespeichert). 1 bedeutet ein brandneues Gerät — neue Geräte bei hochwertigen Aktionen sind ein klassisches Betrugsmerkmal.
device.first_seen string ISO-8601-Zeitstempel, wann Maskbreak dieses Gerät unter Ihrem API-Schlüssel zum ersten Mal gesehen hat. Vorhanden, wenn das Gerät identifiziert wurde — ein sehr junges first_seen neben einer hochwertigen Aktion ist dasselbe Betrugsmerkmal wie times_seen: 1, mit explizit gemachtem Alter.
device.returning boolean True, wenn times_seen > 1 — dieses Gerät wurde schon einmal ausgewertet.
device.linked_accounts integer Mit wie vielen verschiedenen Konten dieses Gerät in den letzten 90 Tagen unter Ihrem API-Schlüssel gesehen wurde. Nur vorhanden, wenn Sie Ihre eigene accountId zusammen mit fingerprintEventId in der Anfrage übergeben. Beide Kennungen werden nur als Einweg-Hashes gespeichert.
device.multi_account boolean True, wenn linked_accounts > 1 — das zentrale Multi-Accounting-Signal (Bonusmissbrauch, Trial-Farming, doppelte Registrierungen). Fügt den Grundcode multi_account_device hinzu.
email.disposable boolean Nur vorhanden, wenn die Anfrage den optionalen Parameter email enthielt. true, wenn die Adresse eine bekannte Wegwerf-Domain nutzt — fügt den Grund disposable_email hinzu und stuft allow zu review hoch.
timezone.reported string Nur vorhanden, wenn die Anfrage eine erkannte tz enthielt. Die vom Browser gemeldete IANA-Zone, zurückgespiegelt.
timezone.country string ISO-3166-1-alpha-2-Land, zu dem diese Zone gehört.
timezone.matches_ip boolean true, wenn das Land der Zone gleich country (dem der Exit-IP) ist. Bauen Sie darauf Ihre eigene Regel, wenn Sie eine strengere Richtlinie als unsere wollen.
timezone.checked boolean false bei VPN-, Proxy-, Tor- oder Rechenzentrums-Exit, wo eine Abweichung erwartet wird und wir nichts auslösen. Bei false lesen Sie matches_ip als Information, nicht als Urteil.
reasons string[] Maschinenlesbare Codes dafür, welche Signale ausgelöst haben (z. B. "vpn_detected", "datacenter_asn", "antidetect_browser").
evaluated_in_ms integer Serverseitige Verarbeitungszeit für diese Anfrage in Millisekunden.
200 OK — Verdächtige Verbindung
{
  "status": "success",
  "isSuspicious": true,
  "decision": "review",
  "risk_score": 65,
  "ip": "185.107.80.12",
  "country": "EE",
  "network": {
    "vpn": true,
    "proxy": false,
    "datacenter": true,
    "tor": false,
    "anonymous": true,
    "residential": false,
    "service": "PROTON_VPN"
  },
  "reasons": ["vpn_detected", "datacenter_asn"],
  "evaluated_in_ms": 126,
  "details": {  /* legacy mirror */
    "ip": "185.107.80.12",
    "cc": "EE",
    "vpn": true,
    "proxied": false,
    "anon": true,
    "dch": true,
    "service": "PROTON_VPN"
  }
}
200 OK — Saubere Verbindung
{
  "status": "success",
  "isSuspicious": false,
  "decision": "allow",
  "risk_score": 0,
  "ip": "82.131.45.9",
  "country": "DE",
  "network": {
    "vpn": false,
    "proxy": false,
    "datacenter": false,
    "tor": false,
    "anonymous": false,
    "residential": true,
    "service": null
  },
  "reasons": [],
  "evaluated_in_ms": 118
}

Wie die Entscheidung zustande kommt

block, wenn ein hartes Signal vorliegt: ein Proxy, ein Tor-Exit, ein Bot oder Automatisierung, ein Emulator oder ein Fake-Browser. review, wenn ein VPN oder ein manipulierter Browser ohne hartes Signal vorliegt. allow sonst — eine Rechenzentrumsadresse oder ein anonymisierendes Netz allein erhöht nur den risk_score. Ihre Regeln können die Antwort jedes Signals überschreiben; das eigene Urteil der Engine wird immer mitgeliefert.

Eingeschränkte Antworten. Erreicht kein Client-Token die API oder ist die Netzwerkschicht nicht erreichbar, liefert der Aufruf trotzdem 200 mit "ip": "unknown", allen Netzwerkflags auf false und decision: "allow". Er wird nicht berechnet und nicht gespeichert. Behandeln Sie das als „kein Beleg“, nicht als sauberen Besucher.

Zusätzliche Flags. test: true bei jeder Antwort auf ein Test-Token oder einen Testschlüssel, sandbox: true, wenn der öffentliche sk_test_sandbox-Schlüssel verwendet wurde, sample: true bei /v1/evaluate/sample. /v1/lookup trägt zusätzlich ein additives network.cloud-Objekt, das den Anbieter nennt, wenn die Adresse in einem veröffentlichten Cloud-Bereich liegt.

Grundcodes

Jeder Wert, den reasons[] tragen kann, und was er bedeutet. Neue Codes kommen nur hinzu.

  • anonymous_network — ein anonymisierendes Netz ohne benannten Betreiber
  • antidetect_browser — ein Fake-Browser (Antidetect-Tooling oder eine manipulierte Umgebung)
  • automation_detected — ein Script oder Headless-Browser
  • datacenter_asn — eine Rechenzentrums- oder Cloud-Adresse
  • disposable_email — eine Wegwerf-E-Mail-Adresse
  • emulator_detected — ein Emulator
  • high_activity_device — ein ungewöhnlich oft gesehenes Gerät (weiches Signal)
  • ip_blocklisted — eine Adresse auf einer Blockliste
  • multi_account_device — ein Gerät, das bereits hinter mehreren Ihrer Konten steckt
  • private_browsing — ein Inkognito- oder privates Fenster
  • proxy_detected — ein Residential- oder Cloud-Proxy
  • timezone_mismatch — die Zeitzone des Browsers widerspricht der Adresse (nur wenn geprüft)
  • tor_exit_node — ein Tor-Exit
  • virtual_machine — eine virtuelle Maschine
  • vpn_detected — ein VPN-Dienst (network.service nennt ihn, wenn bekannt)

Test-Token

Senden Sie eines davon als token mit Ihrem Live-Schlüssel, Ihrem Testschlüssel oder sk_test_sandbox. Mit Ihren eigenen Schlüsseln befolgen sie Ihre Regeln und Ausnahme-Pins (test_vpn ist damit ein Einzeiler, um eine Regel zu prüfen); sie werden nie berechnet. Aus der Konsole gemachte Aufrufe werden als Testzeilen gespeichert, damit das Events-Log etwas zu zeigen hat.

TokenVorgetäuschter BesucherSignaleEntscheidung
test_clean203.0.113.42 · USnichtsallow
test_vpn198.51.100.18 · NLVPN, Rechenzentrum (PROTON_VPN)review
test_proxy203.0.113.9 · DEProxy, Rechenzentrum (BRIGHT_DATA)block
test_datacenter203.0.113.7 · DERechenzentrum (AWS)allow
test_tor203.0.113.99 · nullTor (TOR)block

IP-Lookup

Ein Urteil für eine bloße IP-Adresse — kein Browser-Token nötig. Gleicher Schlüssel, gleiches Stundenkontingent wie /v1/evaluate.

GET /v1/lookup/{ip} — für serverseitiges Screening, wo kein Client läuft: Allowlist-Prüfungen, Batch-Scoring, Anreichern Ihrer eigenen Logs. Nur Netzwerksignale (es gibt kein Gerät zum Fingerprinten), nutzen Sie also /v1/evaluate, sobald ein Browser beteiligt ist. Bei einer bloßen IP greifen die Tor-Exit- und Cloud-Bereichsprüfungen; VPN- und Proxy-Tunnel — und der Dienstname in network.service — werden bei einem Live-Besuch über /v1/evaluate erkannt, sodass signals.vpn und signals.proxied hier false zurückkommen.

curl https://maskbreak.com/v1/lookup/185.220.101.34 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"

{
  "ip": "185.220.101.34",
  "known": true,
  "verdict": "block",            // allow | review | block
  "risk_score": 90,
  "signals": { "vpn": false, "proxied": false, "tor": true, "dch": false, "anon": true },
  "network": { "asn": 205100, "org": "F3 Netze", "country": "DE", "city": null },
  "latency_ms": 121
}

known: false bedeutet, dass keine Intelligence-Quelle eine Meinung hatte — das Urteil ist dann allow mit risk_score: 0, was „nichts gefunden“ heißt, nicht saubere Garantie. Ausnahme-Pins, die Sie im Dashboard konfigurieren, gelten auch hier (verdict_source: "exception" mit additiv erhaltenem engine_verdict). Die Signalschreibweisen (proxied, dch) sind eingefroren — sicher zu parsen.

Ratenlimits

Maskbreak ist in der offenen Beta — jeder Zugang ist kostenlos. Zwei Limits laufen parallel; welches Sie zuerst erreichen, liefert 429.

Geltungsbereich Limit
Pro API-Schlüssel (Kostenlos)1.000 Anfragen / Stunde
Pro API-Schlüssel (öffentliches Interesse)Kein Stundenlimit
Pro Quell-IP50.000 Anfragen / Stunde (freigegebene Schlüssel im öffentlichen Interesse passieren es)

Kein Monatslimit während der Beta. Die Grenze pro IP ist ein Schutz gegen ausufernden Missbrauch von einer einzelnen Maschine. Retry-After ist in jeder 429-Antwort enthalten.

Mit Schlüssel aufgerufene /v1/evaluate- und /v1/lookup-Antworten tragen außerdem X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset (Unix-Sekunden), damit Sie vor dem 429 bremsen können — sowie einen X-Request-Id-Header, den Sie dem Support nennen können, wenn etwas seltsam aussieht.

Schlüssel im Programm für das öffentliche Interesse (Krankenhäuser, öffentliche Gesundheit, Behörden, Wahlen, Rettungsdienste, Universitäten, eingetragene gemeinnützige Organisationen) haben kein Stundenlimit: die drei X-RateLimit-*-Header werden weggelassen statt mit einem Platzhalter gefüllt, und /v1/usage meldet hourly_limit: null mit uncapped: true.

Zuverlässigkeit & Fail-open-Verhalten

Maskbreak fällt offen aus: Ist ein vorgelagerter Anbieter für Netzwerk- oder Geräteintelligenz nicht erreichbar, liefert die Auswertung ihre besten verfügbaren Signale statt eines Fehlers, und ein fehlender Anbieter bedeutet, dass genau diese Signale einfach fehlen (nie eine falsche „sauber“-Garantie). So läuft Ihr Checkout oder Login bei einem Anbieter-Aussetzer weiter, statt alle zu blockieren. Behandeln Sie decision deshalb als beratend und setzen Sie eigene Schwellen — bei kritischen Aktionen ist eine Step-up-Verifizierung bei "review" dem harten Durchlassen vorzuziehen, damit eine eingeschränkte Auswertung eine Bedrohung nicht still durchwinkt. Tritt das ein, trägt die Antwort ein degraded: true auf oberster Ebene; ist das Urteil der bloße saubere Standard, wird der Aufruf nicht in total_evaluations gezählt (Ihr Verbrauch unter /v1/usage und im Dashboard) und nicht in Ihr Events-Log geschrieben — wie jeder authentifizierte Aufruf verbraucht er aber trotzdem eine Anfrage des Stundenlimits, sodass sich X-RateLimit-Remaining bewegt. Ein fehlendes oder leeres Token wird genauso behandelt. Ein Token, das der Anbieter ablehnt (fehlerhaft oder manipuliert), ist kein Anbieterausfall: das liefert 400 Invalid token. und wird ebenfalls nicht gezählt.

Fehlercodes

Alle Fehlerantworten der API enthalten ein error-Stringfeld. Eine Ausnahme, unter 403 vermerkt: eine Sperre am Edge liefert Klartext, kein JSON.

  • 400 Bad Request — Ungültiges token (vom Anbieter abgelehnt oder kein String). Ein fehlendes oder leeres Token ist kein Fehler: es wird fail-open mit degraded: true beantwortet.
  • 401 Unauthorized — Ungültiger oder fehlender API-Schlüssel.
  • 403 Forbidden — Konto gesperrt (kontaktieren Sie support@maskbreak.com), oder die IP des Aufrufers steht nicht auf der IP-Allowlist Ihres Schlüssels (Einstellungen → API-Schlüssel-Sicherheit; das Feld hint nennt die aufrufende Adresse). Von derselben Adresse nicht wiederholbar.

    Dritte Ursache, und die verwirrende: Ein bloßes error code: 1010 als text/plain ohne JSON-Body kommt nicht von uns — das ist unser Edge, der den Standard-User-Agent Ihres HTTP-Clients ablehnt. Python-urllib ist der häufige Fall. Setzen Sie irgendeinen echten User-Agent-Header, und es verschwindet; jedes offizielle SDK tut das bereits.
  • 429 Rate Limited — Stündliches Anfragelimit überschritten (1.000/Std. pro Schlüssel, 50.000/Std. pro Quell-IP). Wird für einen freigegebenen Schlüssel im öffentlichen Interesse nie zurückgegeben.
  • 500 Server Error — Unerwarteter interner Fehler. Kann gefahrlos mit Backoff wiederholt werden.

Verbrauch

Der Quotenstand Ihres Schlüssels als Endpunkt — fragen Sie ihn ab, statt Ratenlimit-Header aus Ihrer letzten Antwort zu kratzen.

GET /v1/usage — authentifizieren Sie sich mit dem API-Schlüssel selbst (Authorization: Bearer …). Funktioniert mit beiden Schlüsseltypen — sk_live_ und sk_test_ melden jeweils ihr eigenes Stundenkontingent, benannt in key_type — und der Aufruf ist kostenlos: er verbraucht nie Quote, sodass ein Monitor, der ihn abfragt, Ihr Limit nicht anknabbern kann.

curl https://maskbreak.com/v1/usage \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"

{
  "key_type": "live",            // or "test"
  "hourly_limit": 1000,
  "used_this_hour": 412,
  "remaining": 588,
  "resets_at": "2026-07-19T11:00:00.000Z",  // end of the rolling 60 minutes that began with your first call; null if nothing used yet
  "total_evaluations": 183204,
  "limit_hits": 3
}

used_this_hour und remaining sind Richtwerte: die Zähler liegen im Speicher und pro Prozess, sie werden bei einem Deployment zurückgesetzt — behandeln Sie sie als Live-Anzeige, nicht als Prüfprotokoll (die Durchsetzung des eigentlichen Limits ist davon unberührt). total_evaluations und limit_hits sind dauerhafte Kontosummen.

Limits und Hinweise. Das Stundenkontingent ist ein rollierendes 60-Minuten-Fenster, das mit Ihrem ersten Aufruf beginnt. Erreicht ein Live-Schlüssel 80 % davon, und erneut, wenn er das Limit trifft, erhält der Kontoinhaber eine E-Mail pro 24 Stunden; der Testschlüssel mailt nie. /v1/usage ist kostenlos aufrufbar, hat aber eine eigene Grenze von 120 Anfragen pro Minute und Adresse (429 mit Retry-After) und antwortet mit 403, wenn die IP-Allowlist des Schlüssels den Aufrufer ausschließt. Wiederholte Aufrufe mit ungültigem Schlüssel sperren die Adresse für 15 Minuten (429, Retry-After: 900).

Webhooks

Bedrohungsalarme an Slack, Discord oder Ihren eigenen Endpunkt — konfiguriert im Integration-Tab der Konsole unter Alarme.

Wann sie auslösen. Bei von der Engine erkannten Bedrohungen (VPN, Proxy, Tor, Rechenzentrum mit Manipulation, Bots, Antidetect-Browser) und bei jeder Auswertung, die Ihre eigenen Regeln mit block entschieden haben. Slack- und Discord-URLs bekommen eine kanalfertige Nachricht; jeder andere HTTPS-Endpunkt erhält ein JSON-Event (event: "threat.detected" mit IP, Bedrohungstyp und den Signaldetails). Der Button Test senden im Dashboard liefert dieselbe Struktur mit event: "test" — wenn Ihr Empfänger strikt nach Event-Typ verzweigt, behandeln Sie beide, sonst sieht der Test-Button wie ein stiller Fehlschlag aus.

Echtheit prüfen. Jede Zustellung ist mit dem Signaturgeheimnis Ihres Kontos signiert (neben der Webhook-URL im Dashboard zu sehen). Berechnen Sie HMAC_SHA256(secret, timestamp + "." + rawBody) mit dem Header X-Maskbreak-Timestamp und vergleichen Sie es (in konstanter Zeit) mit dem Hex-Digest in X-Maskbreak-Signature (nach dem Präfix sha256=). Weisen Sie alles Unsignierte, Abweichende oder Ältere als 5 Minuten zurück.

Empfänger zum Kopieren. Die zwei klassischen Fehler sind, gegen den neu serialisierten geparsten Body statt gegen die rohen Bytes zu prüfen und mit == zu vergleichen. Diese Empfänger machen es richtig:

const crypto = require('crypto');
const express = require('express');
const app = express();

// Raw body required — verify the exact bytes Maskbreak signed,
// never a re-serialized JSON.parse() of them.
app.post('/webhooks/sentinel', express.raw({ type: 'application/json' }), (req, res) => {
  const secret = process.env.SENTINEL_WEBHOOK_SECRET;  // shown next to the URL in the dashboard
  const ts  = req.get('X-Maskbreak-Timestamp') || '';
  const sig = req.get('X-Maskbreak-Signature') || '';

  // Freshness: reject anything older than 5 minutes (replay defense)
  const age = Math.abs(Date.now() / 1000 - Number(ts));
  if (!ts || !Number.isFinite(age) || age > 300) return res.status(400).end();

  // "sha256=" + HMAC_SHA256(secret, timestamp + "." + rawBody), hex digest
  const expected = 'sha256=' + crypto.createHmac('sha256', secret)
    .update(ts + '.').update(req.body).digest('hex');

  // Constant-time compare — never ===
  const a = Buffer.from(sig), b = Buffer.from(expected);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.status(401).end();
  }

  const event = JSON.parse(req.body);  // { event: "threat.detected", event_id, ip, threat_type, details }
  // ... handle it (queue it, alert, block the IP upstream)
  res.status(200).end();  // answer 2xx fast — deliveries time out after 10 s
});
import hashlib, hmac, os, time
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = os.environ["SENTINEL_WEBHOOK_SECRET"].encode()  # shown next to the URL in the dashboard

@app.post("/webhooks/sentinel")
def sentinel_webhook():
    ts  = request.headers.get("X-Maskbreak-Timestamp", "")
    sig = request.headers.get("X-Maskbreak-Signature", "")

    # Freshness: reject anything older than 5 minutes (replay defense)
    try:
        fresh = abs(time.time() - int(ts)) <= 300
    except ValueError:
        fresh = False
    if not fresh:
        abort(400)

    # "sha256=" + HMAC_SHA256(secret, timestamp + "." + raw_body), hex digest.
    # Sign request.get_data() — the exact raw bytes, not request.json.
    expected = "sha256=" + hmac.new(
        SECRET, ts.encode() + b"." + request.get_data(), hashlib.sha256
    ).hexdigest()

    # Constant-time compare — never ==
    if not hmac.compare_digest(sig, expected):
        abort(401)

    event = request.get_json(force=True)  # {"event": "threat.detected", "event_id": ..., "ip": ..., "details": ...}
    # ... handle it (queue it, alert, block the IP upstream)
    return "", 200

Zustellung & Wiederholungen. Jedes Event wird bis zu 3-mal versucht: eine fehlgeschlagene Zustellung wird nach etwa 1 Minute und dann nach etwa 8 Minuten wiederholt. Wiederholungen sind Best-Effort und laufen im Prozess — ein Deployment mitten in der Wiederholung verwirft die restlichen Versuche —, behandeln Sie also das Events-Log im Dashboard als Quelle der Wahrheit und den Webhook als Best-Effort-Push. Die 25 letzten Zustellungen (Event, Ergebnis, Fehler) stehen in der Tools-Schublade des Dashboards, 30 Tage aufbewahrt; der Header-Chip zeigt den aktuellen Zustand, und schlagen 5 Zustellungen in Folge fehl, mailen wir Ihnen — ein toter Webhook darf nie als „keine Bedrohungen“ gelesen werden. Zustellungen laufen nach 10 s ab und folgen nie Weiterleitungen.

Dedupe über event_id. Jede Payload trägt eine event_id — 32 Hex-Zeichen, eindeutig pro Event, auch bei Test-Events vorhanden —, und jede Zustellung trägt sie zusätzlich im Header X-Maskbreak-Event-Id. Wiederholte Zustellungen verwenden dieselbe event_id, schlüsseln Sie Ihre Verarbeitung also darüber, und jedes Event wird genau einmal verarbeitet, egal wie viele Versuche Sie erreichen.

Payload für generische Endpunkte. Was Ihr Empfänger tatsächlich bekommt (Slack-/Discord-URLs erhalten stattdessen eine formatierte Nachricht):

{
  "event": "threat.detected",
  "event_id": "9f2ce7a4c1d84b7fa3d2c05e8b6f4a19",  // unique per event; same on retries
  "timestamp": "2026-07-19T09:14:03.512Z",
  "ip": "185.220.101.34",
  "threat_type": "Tor",              // or "Custom rule (…)" / "Customer exception (…)"
  "details": {
    "ip": "185.220.101.34", "cc": "DE",
    "vpn": false, "proxied": false, "tor": true, "dch": false,
    "bot": false, "tampering": false, "antidetect": false,
    "decision": "block",
    "rule_matched": null,            // signals, when your rule caused the block
    "exception_matched": null        // pins, when your exception caused it
  }
}

MCP für KI-Agenten

Ein gehosteter Model-Context-Protocol-Server — richten Sie einen KI-Agenten darauf, und er kann IPs mit echten Maskbreak-Urteilen prüfen.

Endpunkt: POST https://maskbreak.com/mcp (streamable HTTP, zustandslos). Tools: lookup_ip — dasselbe Urteil wie GET /v1/lookup — und service_status. Authentifizieren Sie sich entweder mit einem klassischen API-Schlüssel Authorization: Bearer sk_live_… oder mit einem OAuth-access_token aus POST /oauth/token. Anonyme Nutzung teilt sich die engen Pro-IP-Limits des kostenlosen Tools; authentifizierte Aufrufe laufen über Ihre Quote von 1.000/Stunde (Ihre IP-Allowlist gilt auch hier).

{
  "mcpServers": {
    "sentinel": {
      "type": "http",
      "url": "https://maskbreak.com/mcp",
      "headers": { "Authorization": "Bearer sk_live_YOUR_API_KEY" }
    }
  }
}

API-Stabilität & Versionierung

Worauf Sie bauen können, ohne sich zu sorgen, dass sich der Boden bewegt.

Versionierung. Die API ist im Pfad versioniert (/v1/). Innerhalb einer Hauptversion machen wir nur additive Änderungen: neue Antwortfelder, neue optionale Anfrageparameter, neue Signalgründe. Ihre Integration muss unbekannte Felder in Antworten tolerieren — das ist die einzige Anforderung an Vorwärtskompatibilität, die wir an Sie stellen.

Breaking Changes. Antwortfelder umbenennen oder entfernen, Typen oder Bedeutungen ändern oder einen Endpunkt zurückziehen passiert nur in einer neuen Hauptversion (/v2/). Wenn dieser Tag kommt, funktioniert /v1/ noch mindestens 12 Monate nach der Ankündigung weiter.

Ankündigung von Abkündigungen. Jede Abkündigung wird mindestens 90 Tage im Voraus über das Changelog und per E-Mail an betroffene API-Schlüssel angekündigt, mit dokumentiertem Migrationspfad. Enterprise-Verträge können längere Supportfenster festschreiben — support@maskbreak.com.

Bereit für echten Traffic?
Kostenloser Schlüssel in unter einer Minute — 1.000 Anfragen/Stunde, keine Karte.
Kostenlos starten Live ausprobieren
FAQ

Häufige Fragen

Wie authentifiziere ich mich bei der Maskbreak-API?
Übergeben Sie Ihren API-Schlüssel als Bearer-Token im Authorization-Header: Authorization: Bearer YOUR_API_KEY. API-Schlüssel werden nach der Registrierung im Dashboard erzeugt, einer pro Konto.
Wie schnell antwortet die API?
Die Entscheidungszeit des Servers liegt im Median unter 150 ms. Das Edge-Netz von Cloudflare steht vor der API, und ein Urteil des ersten Durchlaufs ohne Token wird direkt am Edge beantwortet.
Welche Sprachen und SDKs werden unterstützt?
Offizielle SDKs gibt es für Node.js (@sentinelsup/sdk), Python (sentinelsup) und PHP (sentinelsup/sdk auf Packagist), dazu einen gehosteten MCP-Server für KI-Agenten. Die REST-API lässt sich direkt aus jeder HTTP-fähigen Umgebung aufrufen, einschließlich Go, PHP, Ruby, Java, Rust, C#, Kotlin und Swift.
Was ist in der kostenlosen Stufe enthalten?
1.000 API-Anfragen pro Stunde, ohne Kreditkarte. Jeder Endpunkt ist in der kostenlosen Stufe verfügbar — VPN-Erkennung, Residential-Proxy-Scoring, Antidetect-Browser-Erkennung und Bot-Fingerprinting.
Was passiert, wenn ich mein Ratenlimit überschreite?
Die API liefert HTTP 429 mit einem Retry-After-Header, der sagt, wann das Stundenfenster zurückgesetzt wird. Das Limit liegt bei 1.000 Anfragen/Stunde pro Schlüssel; es gibt keine Bezahlstufe, die es erhöht. Organisationen im öffentlichen Interesse (Krankenhäuser, öffentliche Gesundheit, Behörden, Wahlen, Rettungsdienste, Universitäten, eingetragene gemeinnützige Organisationen) können auf der Seite des Programms für das öffentliche Interesse beantragen, dass das Limit entfernt wird.