Retrieve every occurrence (source + file) for a specific leak hash

GET
/leaks/details/occurrences

Retrieve every distinct detection of a deduplicated credential — one row per (telegram_channel, file_name) pair — read directly from the tenant-routed leaks_matched_* table (no separate occurrence store, no JOIN). The row count EQUALS the occurrences figure shown in the /leaks/details list (same grain), across ALL types (Combo and Stealer).

Use this after /leaks/details to drill into a credential and see each detection. The proprietary telegram_channel and file_name are NEVER returned: the source is replaced by a stable opaque id (opaque_source_id, "Source #" + md5(channel)[:6]) and, when the detection carried a published file, an opaque lot id (opaque_lot_id, md5(file_name)[:6]). Backfilled / historical detections have no file, hence no lot. computer_name is never selected nor returned.

Parameters:

  • hash (required): The leak hash from the /leaks/details response
  • tenant_id_override (optional): workspace (MSSP) only — inspect a child tenant's detail; validated against the caller's portfolio (403/404 otherwise)

Tenant isolation: the query is scoped WHERE tenant_id = <server-derived> AND hash = <param>, so a hash belonging to another tenant returns nothing.

Response:

{
  "total_occurrences": 2,
  "occurrences": [
    {"date": "2026-06-01T10:30:00", "source": "Source #a1b2c3", "lot": "d4e5f6",
     "type": "Stealer", "country": "FR", "stealer_name": "RedLine",
     "software": "Chrome", "ip_address": "1.2.3.4", "machine_user": "admin",
     "machine_id": "…", "protocol": "https"},
    {"date": "2026-05-20T08:00:00", "source": "Source #99aa11", "lot": null,
     "type": "Combo", "country": null, "stealer_name": null, "software": null,
     "ip_address": null, "machine_user": null, "machine_id": null,
     "protocol": null}
  ]
}

Example:

GET /leaks/details/occurrences?hash=5d41402abc4b2a76b9719d911017c592

Authorization

ApiKeyAuth
X-API-Key<token>

API key for authentication

In: header

Query Parameters

hash*Hash

The leak hash to look up

Response Body

application/json

application/json

curl -X GET "https://api.stealed.io/leaks/details/occurrences?hash=string"
{
  "total_occurrences": 0,
  "occurrences": [
    {
      "date": "2019-08-24T14:15:22Z",
      "source": "string",
      "lot": "string",
      "type": "string",
      "country": "string",
      "stealer_name": "string",
      "software": "string",
      "ip_address": "string",
      "machine_user": "string",
      "machine_id": "string",
      "protocol": "string"
    }
  ]
}
{
  "detail": [
    {
      "loc": [
        "string"
      ],
      "msg": "string",
      "type": "string"
    }
  ]
}

Retrieve all occurrences of a specific leak by hash GET

Retrieve all individual occurrences (raw records) for a specific leak hash. Use this after `/leaks/details` to drill down into a deduplicated leak and see every source where the credential was found. **Parameters:** - `hash` (required): The leak hash from the `/leaks/details` response - `identifier_column` (required): `root_domain`, `email_domain`, or `username` **Response:** ```json { "data": [ { "type": "Stealer", "username": "[email protected]", "password": "p****d", "domain": "example.com", "upload_stealed": "2025-01-15T10:30:00", "upload_date": "2025-01-14T08:00:00", "stealer_name": "RedLine", "country": "FR", "ip_address": "1.2.3.4", "computer_name": "DESKTOP-ABC", "software": "Chrome" }, ... ] } ``` **Example:** ```bash GET /leaks/details/by-hash?hash=5d41402abc4b2a76b9719d911017c592&identifier_column=root_domain ```

Paginated, count-sorted distinct-value breakdown for a KPI tile drill-down GET

Drill into a KPI tile (Total Users / Total Domains / Total Sources) with a server-paginated, count-sorted list of distinct values. Reuses the exact same tenant scoping as `GET /leaks/details`: results come from the tenant-routed `leaks_matched_*` table, restricted to the org's active domains, plus all standard `DynamicFilters` (dates, type, domain, not_domain, country, etc.). **Parameters:** | Parameter | Default | Description | |-----------|---------|-------------| | `field` | *required* | `username`, `domain`, or `source` | | `identifier_column` | *required* | `root_domain`, `email_domain`, `username`, or `all` | | `page` | 1 | Page number | | `page_size` | 50 | Items per page (max 200) | | `search` | - | Substring filter on the returned `value` | | `leak_mode` | `new` | `new` (first-seen in period) or `all` (any occurrence in period) -- must match the `/leaks/stats` KPI tile being drilled into | `domain` only counts round-trippable hostnames (drops base64 "email-blob" parsing garbage), matching the Insights domain pie. `source` emits an opaque label (`Source-<md5 prefix>`) -- the real channel name never leaves the API. **Response:** ```json { "data": [{"value": "[email protected]", "count": 42}], "total": 118, "page": 1, "page_size": 50, "total_pages": 3 } ``` `total` is the number of distinct `field` values matching the filters -- the same figure as the corresponding `/leaks/stats` KPI (`unique_usernames` / `unique_domains` / `unique_sources`). **Example:** ```bash GET /leaks/breakdown?field=domain&identifier_column=root_domain&page=1&page_size=50 ```