Scanners
Scanners let you monitor for newly indexedstealer or breach results and receive notifications through email, Discord webhooks, or custom HTTP webhooks.
What Scanners Actually Monitor
Scanners are incremental monitors. They only look for data indexed after the current scanner baseline.
- scanners run on an hourly schedule
- the window is based on
indexed_at, notpwned_at - historical data is not replayed when you create a scanner
- material query changes reset the baseline and begin monitoring from the update time
Scanner Types
Query Config Rules
query_config is close to the live v2 search filters, but it is not a raw request replay.
- allowed flat filters depend on
scanner_type filterandfilter_idare supported- canonical JSON keys such as
domain,email_domain,dbname, andusernameare preferred - bracketed variants such as
domain[]are also accepted - runtime-only parameters are rejected because scanners manage them automatically:
fromtocursorpage_sizeformatdebugsearch_id
- scanners always search with
date_field=indexed_at - scanner configs must contain a durable search anchor, such as a concrete domain, email domain, dbname, username, password hash, log ID, or structured filter leaf
- wildcard-only,
filter_id-only, orextra_params-only configs are rejected because they are not stable enough for hourly monitoring
- if the scanner can be described with exact-match fields, keep
query_configflat - if the scanner needs
or,contains,exists, ranges, or nested groups, usequery_config.filter
filter grammar, step-by-step examples, and filter_id behavior.
Notifications
Webhook Security Modes
signed_jsonDefault mode for new custom webhook scanners. OathNet signs the raw request body with the shared secret.signed_encryptedSigned and encrypted delivery for custom webhook scanners. OathNet signs the encrypted body and includes key metadata in headers.api_keyAvailable only on existing scanners. New scanners should use signed delivery.
- only
httpandhttpsare allowed - IP addresses are rejected
- localhost and private-network hostnames are rejected
- Discord scanners must use a Discord webhook URL
Creating a Scanner
Create scanners with a normalizedquery_config and delivery target. The
create request should describe what to monitor and where to send notifications;
OathNet owns scheduling, baselines, and run windows.
Required fields are name, scanner_type, query_config, and notification_type. webhook_url is also required for webhook and discord notifications.
Delivery Payload
Webhook and Discord notifications include scanner and run metadata plus a sample of matching results. The exactresults.sample shape depends on scanner_type.
signed_encrypted is enabled. Verify signatures against the exact raw request body before parsing JSON.
Verifying Webhook Signatures
Forsigned_json and signed_encrypted, never rebuild the JSON before
verification. Read the exact raw HTTP body bytes, then verify the
X-OathNet-Signature header with HMAC-SHA256.
Signature inputs:
The signed message is:
Python Receiver Example
Node.js Receiver Example
signed_encrypted, first verify the signature against the raw encrypted
envelope body. Then decrypt the JSON envelope with AES-256-GCM using
HKDF-SHA256(secret, info="oathnet-scanner-encryption-v1"). The envelope
contains alg, iv, ciphertext, and kid; ciphertext is base64 encoded and
already includes the GCM tag.
Management Operations
Scanner management is exposed through the public API, but the important product concepts are simple:- quota tells you how many scanners the account can still create
- test delivery sends a sample notification without waiting for the schedule
- manual trigger queues a real run for an active scanner
- pause stops scheduling without deleting the scanner
- resume restarts a paused or disabled scanner after the issue is fixed
- run history shows recent execution and notification outcomes
- run detail explains one specific run and its delivery attempts
Troubleshooting
No results found
- scanners only look for newly indexed data after the current baseline
- use regular search endpoints to inspect historical data
- verify that
query_configcontains valid filters for the scanner type - verify that structured filters target allowed fields for that scanner type
Not receiving notifications
- run a delivery test before waiting for the hourly schedule
- check the saved webhook security configuration
- inspect run history for delivery failures
- verify the webhook target returns a
2xxresponse
Scanner disabled
- scanners are auto-disabled after repeated failures
- fix the delivery or query issue, then resume the scanner
- check quota and plan access if creation or execution is blocked