Retrieve all leak statistics in a single request

GET
/leaks/stats

Retrieve all leak statistics for the current organization in a single request.

This endpoint fetches all leak data once and calculates multiple statistics server-side, reducing the number of queries needed. If start_date and end_date are not provided, defaults to the last 14 days.

Includes trend data comparing the current period to the previous period of the same length (e.g. if querying 30 days, trends compare to the 30 days before that).

Returns a dictionary with the following statistics:

  • total_leaks: Total number of leaks
  • unique_usernames: Number of unique usernames
  • unique_domains: Number of unique domains
  • unique_passwords: Number of unique passwords
  • unique_leaks: Number of unique leak hashes
  • leaks_by_type: Number of leaks grouped by type (combo/stealer)
  • leaks_by_day: Number of leaks grouped by day and identifier (limited globally to 10 top identifiers + other)
  • leaks_by_domain: Number of leaks grouped by domain (limited globally to 10 top domains + other)
  • leaks_by_domain_all: Number of leaks grouped by domain (all domains, no limit)
  • leaks_by_inverse_identifier: Number of leaks grouped by the inverse identifier (email_domain if root_domain, or vice-versa) (limited globally to 10 top + other)
  • top_domains: Top domains with most leaks (limited globally to 10)
  • top_users: Top users with most leaks (all users, no limit)
  • password_strength: Average password length
  • password_reuse: Number of reused passwords
  • password_length_distribution: Distribution of passwords by length
  • external_accounts: Detailed list of external accounts (username, masked password, type, domain, upload_stealed; capped at 50, most recent first)
  • external_accounts_count: Total count of external accounts
  • admin_accounts: Detailed list of admin/privileged accounts (same shape as external_accounts; capped at 50, most recent first)
  • admin_accounts_count: Total count of admin accounts
  • unique_sources: Total number of unique sources (opaque count, channel identity not exposed)
  • sources: List of sources with leak counts (all sources, no limit)
  • latest_leak_date: Date of the latest leak
  • leak_details: All leak details (same as org_leaks_detail_per_identifier, limited to 20000)
  • leaks_by_country: Top 50 countries by leak count (non-empty only)
  • leaks_by_stealer_name: Top 50 stealer families by leak count (non-empty only)
  • leaks_by_software: Top 50 software/browsers by leak count (non-empty only)
  • leaks_by_computer_name: Top 30 computer names by leak count (non-empty only)

Trend Fields (percentage change vs previous period of same length):

  • total_leaks_trend, unique_usernames_trend, unique_domains_trend
  • unique_sources_trend, admin_accounts_count_trend, external_accounts_count_trend

Examples:

# All stats for the last 14 days (default)
GET /leaks/stats?identifier_column=root_domain

# With custom date range
GET /leaks/stats?identifier_column=root_domain&start_date=2024-01-01&end_date=2024-12-31

# With filters
GET /leaks/stats?identifier_column=root_domain&type=Stealer&country=FR

Authorization

ApiKeyAuth
X-API-Key<token>

API key for authentication

In: header

Query Parameters

identifier_column*Identifier Column

Column to use for identifying the domain. Use 'all' for the cockpit cross-scope view (External + Internal union).

Value in"root_domain" | "email_domain" | "username" | "all"
granularity?Granularity

Time granularity for the timeline: 'hour' for hourly buckets (recommended for ranges <= 7 days), 'day' for daily buckets

Default"day"
Value in"hour" | "day"
leak_mode?Leak Mode

Leak counting mode: 'new' counts only credentials first discovered in the period, 'all' counts any credential with at least one occurrence in the period.

Default"new"
Value in"new" | "all"
include_all_time?Include All Time

When true, include all-time aggregates (all_time_total_leaks, all_time_unique_users, all_time_unique_hosts, all_time_unique_passwords) computed without date filtering. Used by the cockpit landing page to render '% of total' lines.

Defaultfalse
facets?Facets

When false, skip the metadata facet aggregations (country, stealer_name, software, computer_name, protocol, root_domain, email_domain). Only leaks_by_type is still computed (cockpit needs the Stealer count). Cuts the internal CH fan-out from ~12 sub-queries down to ~5. The Insight pages keep the default and receive the full payload.

Defaulttrue
timeline?Timeline

When false, skip the per-bucket timeline query that powers the TimeRangeBrush. The cockpit doesn't render a brush, saves one extra CH scan per call.

Defaulttrue
username?|array<string>|

Username of the leaked user (can be phone, email, ID, ...)

type?|array<string>|

Type of leak (combo, stealer)

hash?|array<string>|

Uniq identifier for the concatenation of : username, password and domain

upload_stealed?||array<|string>|

Upload date on stealed, ISO 8601, pattern YYYY-MM-DD

upload_date?||array<|string>|

Upload date on the plateform the credential was found, ISO 8601, pattern YYYY-mm-dd

log_date?||array<|string>|

Log date of the device at compromized moment (if applicable, stealer only)

start_date?||

Start date to search from leaks, format: YYYY-mm-dd (default: today - 14days at 0:00am)

end_date?||

End date to search leaks from, format YYYY-mm-dd (default: today)

host?|array<string>|

URL of the leaked data

domain?|array<string>|

FQDN of the leaked data

local_part?|array<string>|

Local part of the username section (if applicable, email only)

protocol?|array<string>|

Protocol identified (if applicable)

email_domain?|array<string>|

Email domain to filter on (if multiple email domains declared)

root_domain?|array<string>|

Root domain to filter on (if multiple root domains declared)

machine_id?|array<string>|

Machine ID (if applicable, stealer only)

computer_name?|array<string>|

Computer name (if applicable, stealer only)

hardware_id?|array<string>|

Hardware ID (if applicable, stealer only)

machine_user?|array<string>|

Machine user (if applicable, stealer only)

ip_address?|array<string>|

IP address (if applicable, stealer only)

country?|array<string>|

Country (if applicable, stealer only)

software?|array<string>|

Software (if applicable, stealer only)

stealer_name?|array<string>|

Stealer name (if applicable)

source?|array<string>|

Opaque source label(s) to filter on, of the form Source-<6 hex> (as returned by the sources breakdown). The raw telegram_channel is never exposed: the label is matched back against the same MD5-prefix expression server-side.

keyword?|array<string>|

Keyword to filter on (only active keywords for tenant)

match_type?|array<string>|

Match type for leaks_matched table (root_domain or email_domain)

not_root_domain?|array<string>|

Root domains to exclude (NOT IN filter)

not_email_domain?|array<string>|

Email domains to exclude (NOT IN filter)

not_domain?|array<string>|

Domains to exclude (NOT IN filter)

not_type?|array<string>|

Types to exclude

not_software?|array<string>|

Software to exclude

not_stealer_name?|array<string>|

Stealer names to exclude

not_protocol?|array<string>|

Protocols to exclude

not_country?|array<string>|

Countries to exclude

first_seen_date?|

Show only hashes whose first appearance (min upload_stealed) falls on this exact date. Format: YYYY-MM-DD.

first_seen_since?|

Show only hashes whose first appearance (min upload_stealed) is on or after this date. Format: YYYY-MM-DD.

limit?|

Limit result length

min_occurrences?|

Minimum number of sources (source_count >= N)

Response Body

application/json

application/json

curl -X GET "https://api.stealed.io/leaks/stats?identifier_column=root_domain&granularity=day"
null
{
  "detail": [
    {
      "loc": [
        "string"
      ],
      "msg": "string",
      "type": "string"
    }
  ]
}

[Deprecated] Retrieve leaks for the current user/organization for a given query GET

**Deprecated**: For leak details, use `GET /leaks/details` which provides pagination, deduplication, search, and sorting. For keyword search, use `GET /leaks/keyword/search`. Retrieve leak statistics for the current organization. Each call returns a single statistic based on the `query` parameter. Both `query` and `identifier_column` are **required**. If `start_date` and `end_date` are not provided, defaults to **the last 14 days**. **Required Parameters:** - `query`: The statistic to retrieve (see query types below) - `identifier_column`: `root_domain`, `email_domain`, or `username` **Available Query Types:** **Generic Queries (counts and aggregates):** - `generic_total_leaks_count`: Total leaks count - `generic_uniq_username_count`: Unique usernames detected - `generic_uniq_source_count`: Unique sources with at least one detection - `generic_uniq_password_count`: Unique passwords detected - `generic_uniq_domain_count`: Unique domains detected - `generic_uniq_leaks_count`: Unique leaks (by hash) - `generic_latest_leak_date`: Date of the latest leak - `generic_reused_password_count`: Passwords reused across multiple domains - `generic_password_strength`: Average password length **Generic Queries (detailed data):** - `generic_leaks_type_by_identifier`: Leaks grouped by type (combo/stealer) - `generic_leaks_by_day`: Leaks per day - `generic_password_per_length_per_identifier`: Password distribution by length - `generic_most_recent_leaks_by_identifier`: Most recent leaks **Organization Queries:** - `org_uniq_priv_account_count`: Privileged accounts leaked (admin, root, etc.) - `org_detailed_uniq_admin_account_count`: Detailed list of admin accounts - `org_uniq_ext_account_count`: External accounts count - `org_detailed_uniq_ext_account_count`: Detailed list of external accounts - `org_detailed_uniq_username_count`: Detailed list of all usernames - `org_total_leaks_count_group_by_identifier`: Leaks grouped by identifier - `org_total_leaks_count_group_by_domain`: Leaks grouped by domain - `org_total_leaks_count_group_by_email_domain`: Leaks grouped by email domain - `org_total_leaks_count_group_by_root_domain`: Leaks grouped by root domain - `org_top_domain_leaks_by_identifier`: Top domains by leak count - `org_top_user_leaks_by_identifier`: Top users by leak count - `org_leaks_detail_per_identifier`: Full leak details per identifier **Examples:** ```bash # Total leaks count GET /leaks/me?query=generic_total_leaks_count&identifier_column=root_domain # Unique usernames GET /leaks/me?query=generic_uniq_username_count&identifier_column=root_domain # Stealer leaks only GET /leaks/me?query=generic_total_leaks_count&identifier_column=root_domain&type=Stealer # Leaks per day with date range GET /leaks/me?query=generic_leaks_by_day&identifier_column=root_domain&start_date=2025-01-01&end_date=2025-01-31 # Leaks grouped by domain, limited to 100 GET /leaks/me?query=org_total_leaks_count_group_by_domain&identifier_column=root_domain&limit=100 # Multiple domain filter GET /leaks/me?query=org_total_leaks_count_group_by_domain&identifier_column=root_domain&domain=test.example.com&domain=monitoring.example.com ```

Retrieve paginated leak details with optional search GET

Retrieve paginated, deduplicated leak details for the current organization. Results are **deduplicated by hash**: each unique credential (username + password + domain) appears once, with aggregated metadata from all occurrences. **Specific Parameters:** | Parameter | Default | Description | |-----------|---------|-------------| | `identifier_column` | *required* | `root_domain`, `email_domain`, or `username` | | `page` | 1 | Page number | | `page_size` | 50 | Items per page (max: 200) | | `search` | - | Full-text search across username, host, domain, email_domain, root_domain, ip_address, computer_name, machine_user | | `sort_by` | `source_count` | Sort order: `source_count` (most seen first) or `last_seen` (most recent first) | | `min_occurrences` | - | Only return credentials seen in N+ distinct sources | Plus all standard filters (see API description above). **Response Fields:** | Field | Type | Description | |-------|------|-------------| | `username` | string | Username or email. The local part (before the `@`) is not returned separately, derive it client-side if needed | | `password` | string | Masked password: first and last character, one `*` per character in between (starred whole under 6 characters). See `unmask` for the clear value | | `types` | string[] | All distinct leak types for this credential, e.g. `["Combo", "Stealer"]`. A credential found in both Combo dumps and Stealer logs will have both values. | | `type` | string | **Deprecated** (flagged in the schema). Single type value, the most recent ingestion's. Use `types`. | | `last_seen` | datetime | Most recent detection date (aggregated `max(upload_stealed)` across all occurrences) | | `upload_date` | datetime | **Deprecated** (flagged in the schema). Source file publication date. Duplicates `last_seen` on the default per-hash read; use `last_seen` | | `log_date` | datetime | Infostealer log creation date, **as declared by the malware**: sparse and partly bogus (see the note below). Representative value | | `first_seen` | datetime | Earliest detection date (`min(first_seen)`, the credential's global first discovery, NOT `min(upload_stealed)`: it can predate this tenant's earliest occurrence) | | `source_count` | int | **Deprecated** (flagged in the schema). Legacy proxy metric `uniq(file_name, stealer_name, country)`. Prefer `sources`/`occurrences`/`files`. | | `sources` | int | Number of distinct sources reporting this credential (`uniqExactIf(telegram_channel)`, floored by the backfill HLL snapshot and by 1), from `leaks_matched` | | `occurrences` | int | Number of distinct (source, file) detections all-time (`uniqExact((telegram_channel, file_name))`) for this credential | | `files` | int | Number of distinct named files (`uniqExactIf(file_name, going-forward)`) this credential was found in | | `domain` | string | Associated domain | | `host` | string | Full URL or host | | `email_domain` | string | Email domain part | | `root_domain` | string | Root domain | | `country` | string | ISO 2-letter country code. Representative value (see note below) | | `stealer_name` | string | Stealer family (RedLine, Raccoon, etc.). Representative value | | `software` | string | Browser/app. Representative value | | `protocol` | string | Protocol (https, android, ...). Representative value | | `ip_address` | string | Victim IP address. Representative value | | `computer_name` | string | Machine name. Representative value | | `machine_id` | string | Machine id. Representative value | | `machine_user` | string | Machine user account. Representative value | | `hardware_id` | string | Hardware id. Representative value | | `log_date` | datetime | Date of the infostealer log. Representative value | | `countries` | string[] | EVERY country this credential was seen from | | `stealers` | string[] | EVERY stealer family | | `softwares` | string[] | EVERY browser/app | | `protocols` | string[] | EVERY protocol | | `hosts` | string[] | EVERY host, normalised to a bare hostname | | `ip_addresses` | string[] | EVERY victim IP | | `machine_users` | string[] | EVERY machine user account | | `computer_names` | string[] | EVERY machine name | | `machine_ids` | string[] | EVERY machine id | | `hardware_ids` | string[] | EVERY hardware id | | `hash` | string | Unique deduplication hash | **Note:** Results are deduplicated by hash. The raw `upload_stealed` column is not returned directly. Instead, `first_seen` and `last_seen` are computed as `min(upload_stealed)` and `max(upload_stealed)` across all occurrences of each credential. **About `log_date`.** It is written by the malware inside the stealer log, not by us: only ~0.2% of raw occurrences carry one (~44% of credentials once aggregated), and a few are dated in the future. Treat it as indicative. **Representative values vs sets.** One credential (hash) is typically seen in several infostealer logs, and the machine-level values can differ between them. Each such field is returned twice: the singular field (`software`, `country`, `ip_address`, ...) carries ONE representative value, the most recent occurrence's, and the plural field (`softwares`, `countries`, `ip_addresses`, ...) carries the deduplicated set of EVERY value seen across all occurrences. Empty values are dropped, so a Combo-only credential returns `[]` and never `[""]`. A credential seen in three logs from three countries returns `"country": "FR"` and `"countries": ["FR", "MX", "ID"]`. These sets are materialised per credential in the read model, so they cost nothing extra to return. What they do NOT give is the pairing between values (which IP went with which browser, on which date): for that, call `GET /leaks/details/occurrences?hash=...`, which returns every (source, file) detection with its own machine metadata. **Response Format:** ```json { "data": [ { "username": "user@example.com", "password": "p****d", "types": ["Stealer"], "type": "Stealer", "first_seen": "2025-01-15T08:30:00", "last_seen": "2025-03-01T12:00:00", "host": "login.example.com", "domain": "login.example.com", "protocol": "https", "email_domain": "example.com", "root_domain": "example.com", "upload_date": "2025-02-28T10:00:00", "log_date": "2025-02-27T14:00:00", "machine_id": "DESKTOP-ABC1234", "computer_name": "LAPTOP-XYZ", "hardware_id": "hwid-1234-5678", "machine_user": "john.doe", "ip_address": "192.168.1.10", "country": "FR", "software": "chrome, profile: 0", "stealer_name": "RedLine", "countries": ["FR", "BE"], "stealers": ["RedLine", "Lumma"], "softwares": ["chrome, profile: 0", "Opera GX, Profile: 0"], "protocols": ["https"], "hosts": ["login.example.com"], "ip_addresses": ["192.168.1.10", "10.0.0.4"], "machine_users": ["john.doe"], "computer_names": ["LAPTOP-XYZ"], "machine_ids": ["DESKTOP-ABC1234"], "hardware_ids": ["hwid-1234-5678"], "hash": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4", "source_count": 3, "sources": 2, "occurrences": 3, "files": 3 } ], "total": 12345, "page": 1, "page_size": 50, "total_pages": 247 } ``` **Examples:** ```bash # Basic paginated request GET /leaks/details?identifier_column=root_domain&page=1&page_size=50 # Sort by most recent GET /leaks/details?identifier_column=root_domain&sort_by=last_seen # Sort by number of distinct sources (leaks_matched-derived) GET /leaks/details?identifier_column=root_domain&sort_by=sources # Only credentials seen 3+ times GET /leaks/details?identifier_column=root_domain&min_occurrences=3 # Full-text search with filters GET /leaks/details?identifier_column=root_domain&search=john&type=Stealer&country=FR # Custom date range GET /leaks/details?identifier_column=root_domain&start_date=2024-01-01&end_date=2024-12-31&page_size=200 ``` **Pagination (retrieve all results):** ```bash # Page 1 GET /leaks/details?identifier_column=root_domain&page=1&page_size=200 # Page 2 GET /leaks/details?identifier_column=root_domain&page=2&page_size=200 # ... continue until page >= total_pages ```