Scanners
Scanners let you monitor for newly indexed stealer 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, not pwned_at
- historical data is not replayed when you create a scanner
- material query changes reset the baseline and begin monitoring from the update time
Use the regular search endpoints when you need to investigate historical data.
Scanner Types
| Type | Backing search surface | Typical use |
|---|
stealer | /service/v2/stealer/search | Monitor credentials, domains, usernames, passwords, subdomains, or log IDs |
breach | /service/v2/breach/search | Monitor breach records, dbnames, names, phone numbers, email domains, and similar fields |
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
filter and filter_id are supported
- canonical JSON keys such as
domain, email_domain, dbname, and username are preferred
- bracketed variants such as
domain[] are also accepted
- runtime-only parameters are rejected because scanners manage them automatically:
from
to
cursor
page_size
format
debug
search_id
- scanners always search with
date_field=indexed_at
Simple rule:
- if the scanner can be described with exact-match fields, keep
query_config flat
- if the scanner needs
or, contains, exists, ranges, or nested groups, use query_config.filter
See Structured Filters for the shared filter grammar, step-by-step examples, and filter_id behavior.
Notifications
| Notification type | Notes |
|---|
email | Sends to your OathNet account email |
discord | Requires a Discord webhook URL |
webhook | Requires a custom HTTP or HTTPS endpoint reachable by OathNet |
Webhook Security Modes
signed_json
Default mode for new custom webhook scanners.
signed_encrypted
Signed and encrypted delivery for custom webhook scanners.
api_key
Legacy-only mode. New scanners cannot opt into it.
Webhook URLs are validated aggressively:
- only
http and https are allowed
- IP addresses are rejected
- localhost and internal hostnames are rejected
- Discord scanners must use a Discord webhook URL
Creating a Scanner via API
Use POST /scanners/create with a normalized query_config and delivery target.
{
"name": "Example breach monitor",
"scanner_type": "breach",
"query_config": {
"filter": {
"and": [
{ "field": "email_domain", "operator": "eq", "value": "example.com" },
{ "field": "dbname", "operator": "in", "value": ["twitter.com", "linkedin.com"] }
]
}
},
"notification_type": "webhook",
"webhook_url": "https://alerts.example.com/oathnet",
"webhook_security_mode": "signed_json",
"notify_on_zero_results": false
}
Before saving a webhook or Discord scanner, you can validate delivery with POST /scanners/test-delivery.
Delivery Payload
Webhook and Discord notifications include scanner and run metadata plus a sample of matching results. The exact results.sample shape depends on scanner_type.
{
"event": "scanner.results_found",
"scanner": {
"uid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Example breach monitor",
"type": "breach",
"query_config": {
"email_domain[]": ["example.com"]
}
},
"run": {
"uid": "660e8400-e29b-41d4-a716-446655440001",
"search_from": "2026-04-18T00:00:00Z",
"search_to": "2026-04-18T01:00:00Z"
},
"results": {
"count": 5,
"sample": [
{
"email": "user@example.com",
"dbname": "twitter.com",
"indexed_at": "2026-04-18T00:45:00Z"
}
]
},
"search_url": "https://oathnet.org/search?...",
"timestamp": "2026-04-18T01:00:00Z"
}
Use GET /scanners/{scanner_uid}/webhook-security to inspect the configured verification method and delivery headers.
Operational Endpoints
GET /scanners/quota
View current scanner quota.
POST /scanners/{scanner_uid}/test
Send a real test notification for an existing scanner.
POST /scanners/{scanner_uid}/trigger
Queue an immediate run for an active scanner.
POST /scanners/{scanner_uid}/pause
Pause scheduling without deleting the scanner.
POST /scanners/{scanner_uid}/resume
Resume a paused or disabled scanner.
GET /scanners/{scanner_uid}/runs
Review recent run history.
GET /scanners/{scanner_uid}/runs/{run_uid}
Inspect a specific run and its notification 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_config contains valid filters for the scanner type
- verify that structured filters target allowed fields for that scanner type
Not receiving notifications
- use
POST /scanners/test-delivery or POST /scanners/{scanner_uid}/test
- check
GET /scanners/{scanner_uid}/webhook-security
- inspect run history for delivery failures
- verify the webhook target returns a
2xx response
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
Scanner Management API
Scanner management is available today through the public API. The full surface is documented under the Scanners API Reference, and the same API key authentication model applies there as well.