Paginated, count-sorted distinct-value breakdown for the keyword insight KPI tiles

GET
/leaks/keyword/breakdown

Drill into a keyword-insight KPI tile (Total Users / Total Domains) with a server-paginated, count-sorted list of distinct values, computed from the organization's active keywords over leaks_history (same dedup-by-hash rows as GET /leaks/keyword/search).

field=source is rejected (returns an empty page): keyword leaks have no reliable per-credential source attribution (see the keyword teaser-tier rule) -- classic leaks use GET /leaks/breakdown?field=source instead.

Parameters:

ParameterDefaultDescription
fieldrequiredusername, domain, or source (rejected, empty page)
page1Page number
page_size50Items per page (max 200)
search-Substring filter on the returned value

Plus all standard DynamicFilters, exactly like GET /leaks/keyword/search.

Response:

{
  "data": [{"value": "acme-corp-recrute.talent-soft.com", "count": 12}],
  "total": 34,
  "page": 1,
  "page_size": 50,
  "total_pages": 1
}

total is the number of distinct field values matching the filters -- the same figure as unique_usernames / unique_domains from GET /leaks/keyword/stats.

Example:

GET /leaks/keyword/breakdown?field=domain&page=1&page_size=50

Authorization

ApiKeyAuth
X-API-Key<token>

API key for authentication

In: header

Query Parameters

field*Field

KPI dimension to break down

Value in"username" | "domain" | "source"
page?Page

Page number

Default1
Range1 <= value
page_size?Page Size

Items per page (max 200)

Default50
Range1 <= value <= 200
search?Search

Substring filter on the returned value

Lengthlength <= 200
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/keyword/breakdown?field=domain"
{
  "data": [
    {
      "count": 42,
      "value": "[email protected]"
    },
    {
      "count": 17,
      "value": "[email protected]"
    }
  ],
  "page": 1,
  "page_size": 50,
  "total": 118,
  "total_pages": 3
}
{
  "detail": [
    {
      "loc": [
        "string"
      ],
      "msg": "string",
      "type": "string"
    }
  ]
}

Paginated keyword search results GET

Retrieve paginated leak details matching the organization's active keywords. Returns the same paginated envelope as `/leaks/details`. The row shape differs slightly: keyword rows come from the occurrence grain, so they carry `local_part` and no per-credential value sets (`softwares`, `ip_addresses`, ...). This endpoint has an additional `matched_keyword` field indicating which keyword matched each row. Searches `leaks_history` for rows where `hasToken(host, keyword)` is true for any active keyword, excluding the org's own monitored root domains. If the organization has no active keywords, returns an empty paginated response. **Parameters:** | Parameter | Default | Description | |-----------|---------|-------------| | `page` | 1 | Page number | | `page_size` | 50 | Items per page (max 200) | | `search` | - | Full-text search across username, host, domain, root_domain | | `sort_by` | `last_seen` | Sort order: `last_seen` (most recent first) | | `start_date` / `end_date` | last 14 days | Date range filter | Plus all standard DynamicFilters. **Response Format:** ```json { "data": [ { "username": "[email protected]", "password": "p****d", "type": "Stealer", "last_seen": "2026-03-15T10:30:00", "host": "acme-corp-recrute.talent-soft.com", "domain": "acme-corp-recrute.talent-soft.com", "local_part": "user", "protocol": "https", "email_domain": "example.com", "root_domain": "talent-soft.com", "log_date": "2026-03-10T08:00:00", "country": "FR", "software": "chrome, profile: 0", "stealer_name": "RedLine", "hash": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4", "machine_id": "DESKTOP-ABC1234", "computer_name": "LAPTOP-XYZ", "hardware_id": "hwid-1234-5678", "machine_user": "john.doe", "ip_address": "192.168.1.10", "upload_date": "2026-03-14T12:00:00", "source_count": 1, "matched_keyword": "acme-corp" } ], "total": 12345, "page": 1, "page_size": 50, "total_pages": 247 } ``` **Examples:** ```bash # Basic paginated request GET /leaks/keyword/search?page=1&page_size=50 # With search filter GET /leaks/keyword/search?search=admin&page=1&page_size=50 # With date range GET /leaks/keyword/search?start_date=2026-03-01&end_date=2026-03-28 ```

Retrieve sources for a keyword leak by hash GET

Get all occurrences of a keyword leak from leaks_history by hash. Scoped to the tenant's active keywords for security.