Skip to main content
Filtered credentials is the cleaned-up view of the leaked accounts on one domain. It reads the same leak data as Raw Data, then deduplicates it, scores every account, and lets you arrange the results by category. Raw Data hands you every record to work through. Filtered credentials hands you one list of distinct accounts on one domain, typically your organization’s own, such as acme.com. In the dashboard, this is Filtered Credentials, both as a Search by Source tile and as a Unified Search tab. Availability: every plan with a license in force. No plan feature is checked. Cost: no metered allowance. With an API key, each call counts once toward your monthly API Calls allowance, polls and result pages included, and only 2xx responses count. See Rate limits. When your organization’s license is not active, every endpoint on this page returns 403 with {"detail": "Your license is not active."}. These endpoints never return the plan-feature 403, an allowance 429 or a capacity 409. See Plans and quotas.
Want the machine, not the account? Filtered credentials returns a deduplicated account list. Stealer logs searches the same corpus by infected device, and returns the whole capture: session cookies, screenshots and everything else that was on the machine.
You typically point a search at your organization’s own domain, but ownership is not checked. Any domain can be searched, subject to the two checks below. Pass it bare, as acme.com or mail.acme.com, without a scheme or path. The two checks refuse very large domains:
  • The blocklist. About 1,000 free-mail and consumer domains cannot be searched. The check runs when you create the search. The task comes back already failed, with this error_message:
  • The 5,000,000-record ceiling. The first search for a domain counts its leaked records in the background. The task starts as pending. If the domain has more than 5,000,000 leaked records, the task moves to failed with this error_message:
The count runs once per domain, and the verdict is kept. After a domain passes, later searches skip the count. After it fails, later searches of that domain fail as soon as you create them, with the same message. A domain registered to an active DarknetSearch organization skips the ceiling. To look up a single address on a public mail provider, use the ULP feed. It has no domain restriction. To check one credential from your own sign-in flow, use Credential Check. A filtered search is asynchronous: pick a filter, create the search, poll it until it ends, then read the accounts.
1

Pick a filter

leak_filter_filters returns the filter catalog. Each filter has an id, name, description and parameters_schema. The filter_id you pick is the arrangement: it decides which slice of the domain’s accounts comes back, and whether you send filter_parameters.filter_id is required on every call that takes it. Unique Credentials (5) returns the full deduplicated set, and it is the arrangement the dashboard opens with. The IDs below are the ones the platform defines. Confirm them against leak_filter_filters.The Include and Exclude filters take comma-separated terms and match a case-insensitive substring, so alice also matches alice.smith.
2

Create the search

leak_filter_search_create takes a JSON body with domain_url, filter_id and mode, plus filter_parameters when your filter needs them.
Narrow to one or more usernames with Include Usernames (filter_id 1). The key is plural, usernames:
mode decides what happens when only part of the data could be processed:The call returns 201 with the task: its id, status, error_message, domain_url, mode, filter_name and timestamps. Keep the id. A blocklisted domain still returns 201, with status already failed. Read status before you start polling.Invalid input returns 400 instead, and no task is created: a malformed domain_url, a filter_id that does not exist, or filter_parameters that do not match the filter’s parameters_schema.
3

Poll until the task ends

Pass the task id as filter_task_id to leak_filter_search_retrieve. Poll about every 30 seconds.
Stop on ready, incomplete_ready or failed. A failed task stays failed. Fix the cause, then create a new search.The first search for a domain does the heavy work. It walks every leak exposing that domain since 23 September 2020, deduplicates the accounts and scores each one. Depending on how much is exposed, it can take several minutes. The accounts are then stored per domain. Every later search for the same domain processes only the leaks found since the last run, so it finishes much faster.
4

Read the accounts

Once the task is ready or incomplete_ready, read its accounts from leak_filter_search_results with the same filter_task_id:
The response is a page of accounts: count, next, previous and results. Read it too early and you get 404 with {"error_message": "Filter task is not ready. Current status: in_progress"}. Read a failed task and you get 400 with {"error_message": "Cannot process filter task. Processing has failed."}.

Read a domain without a task

A domain’s accounts stay stored after its first search. leak_filter_domain_search_results reads them straight from the domain, with no task to track. It takes domain_url and filter_id, and returns the current accounts. The dashboard’s Filtered Credentials results use this call.
On this call, filter_parameters is a JSON string in the query, so URL-encode it:
The domain must exist and be active: This 403 carries error_message, not detail. It is about the domain, not your license or plan.

Page through results

Both result calls page the same way: page × page_size cannot exceed 50,000. Past that, the call returns 400 with Pagination depth limit exceeded. page * page_size must be <= 50000. Use a narrower filter or the export endpoint. Narrow the filter or export the results. A page past the last one returns an empty results list. Step through pages by increasing page until you have read count accounts. Do not follow the next and previous links. They do not point at client-api.leak.center.

Filter and sort results

Both result calls and both export calls take the same optional filters, as query parameters: On a result call, a date in any other format returns 400 with Invalid date format, expected YYYY-MM-DD. Sort with order and direction (asc or desc). The default is created_at, descending. The dashboard sorts by novelty_score, descending. On a result call, any other order or direction returns 400. On an export call, these values are not checked up front. The call returns 202, and a bad date or an unknown password policy ID makes the job end failed, with the reason in error_message. An unknown order or direction falls back to created_at, desc.

What comes back

Each account row carries the credential, where it was used, when it surfaced, and how it scores:
  • Identifiers. id is the account row. record_id is the leaked record it came from. created_at is when that record was indexed.
  • The credential. server, username and password. server reads - when the leak named no server, and has_url is then false.
  • Classification. is_infrastructure, is_business, is_private and has_url.
  • Scoring. novelty_score, risk_score, reuse_count_till_creation_time and first_discovery.
  • Provenance. leaks (each with leak_id and leak_name), leak_publish_date, leak_discover_date and tags.
  • Policy match. matches_password_policy is null unless you send pwd_policy_ids.
The list is already deduplicated. Each domain stores one row per server + username + password. The same login on a different server stays a separate row, because it is a different exposure.

How novelty and risk are scored

novelty_score and risk_score are computed, not copied from the leak. Both run from 0 to 10. Novelty: how fresh a credential is. It is the average of two sub-scores. Recency, from when the credential was first seen: Reuse, from how many earlier records already held the same username and password: When first_discovery is unknown, both sub-scores count as 5. A new, never-seen credential scores 10. An old, heavily reused one scores 2. Risk: how urgently it deserves attention. A weighted average of four inputs, each scaled to 0–1, then multiplied by 10:
A fresh credential on your own infrastructure scores highest. An old login on a personal service scores lowest. is_private is recorded on the row, but it does not change the score. Both scores round halves to the nearest even number. With the default weights, both are set when the record is analyzed. Once you change any weight, both are computed each time you read, from the age of the credential at that moment.

Tune the weights

Six weights shape the scores for your organization, each from 0 to 5: first_discovery_weight and reuse_weight cannot both be 0, and at least one of the four risk weights must be above 0. Otherwise the call returns 400. Read them with leak_filter_risk_settings_retrieve. Change them with leak_filter_risk_settings_update, sending all six:
The new weights apply from your next read.

Match against your password policy

A leaked password that still satisfies your current password policy is more likely to still be in use. Filtered credentials can flag those rows. Define a policy once, then apply it to any read. Define it. A password policy belongs to your organization. Create one with leak_filter_password_policies_create:
A policy is a minimum length plus up to three character-class rules: min_length (default 8), require_numbers, require_special_chars and require_uppercase (all default false). A password matches when it reaches min_length and meets each rule you turned on: at least one digit, at least one A–Z, and at least one of !@#$%^&*(),.?":{}|<>. Your organization can hold up to 5 policies, each with a unique name. A sixth returns 400 with Maximum number of password policies (5) reached for this organization. List, read, update and delete policies with leak_filter_password_policies_list, leak_filter_password_policy_retrieve, leak_filter_password_policy_update and leak_filter_password_policy_delete. Apply it. Pass pwd_policy_ids on a results or export call:
Every row then carries matches_password_policy as true or false. It tags rows, it does not filter them. Non-matching accounts still come back, so you keep the full picture and can sort or triage by the flag. Pass several IDs, and a row is flagged when it matches any of them. On a result call, an ID that is not one of your policies returns 400 with Password policy not found. On an export call, the job ends failed with that message in error_message.

Export the results

To pull a full result set as one file instead of paging, create an export. Filtered credentials has its own export endpoints. For exports from other sources, see Downloads and exports.
1

Create the export

Every parameter goes in the query string, including on these POST calls. file_type is required: json, csv or xlsx. The filters and sort from Filter and sort results apply too.Export a finished task with leak_filter_export_create_from_filter_task. The export uses the task’s filter and filter_parameters:
Or export a searched domain with leak_filter_export_create_from_domain, passing domain_url and filter_id, plus filter_parameters as a JSON string when the filter needs them:
Both return 202 with the export job:
The same rules as reading apply. A task export needs a ready or incomplete_ready task, so an unfinished task returns 404 and a failed one returns 400. A domain export needs an existing, active domain, so you get the 404 and 403 described in Read a domain without a task. A missing or unknown file_type returns 400. Dates, order, direction and pwd_policy_ids are not checked here. See Filter and sort results.
2

Poll until it ends

Poll leak_filter_export_retrieve with the export id:
status moves from pending to running, then ends ready or failed. A ready job fills in result_count (rows) and size (bytes). A failed job carries error_message.
3

Download the file

Fetch the file from leak_filter_export_download. It arrives as an attachment named export-<id>.<file_type>.
This 409 means the file is not ready yet. It is not a capacity refusal.
Files expire 24 hours after the export is created. leak_filter_export_list lists your organization’s exports from the last 24 hours, newest first. Filter it by file_type, status or filter_ids (comma-separated), and page it with page (from 1) and page_size (default 50, up to 100).

Manage search tasks

leak_filter_search_list lists your organization’s search tasks, newest first. Filter it by status, or by domain_url (a case-insensitive substring). Page it with page (from 1) and page_size (default 10, up to 100).
leak_filter_search_delete deletes tasks by ID. Pass them comma-separated in filter_task_ids:
Only your organization’s tasks are deleted. IDs that are not yours are skipped. Deleting a task does not delete the domain’s stored accounts, so leak_filter_domain_search_results still reads them.

Get notified about new accounts

A filtered search runs when you call it. To be notified when new accounts appear on a domain, create a monitor on the Leak Filter source (service 6). It takes the same domain_url and filter_id. A blocklisted domain, or one already counted over the ceiling, is refused there too.

Errors

A blocklisted or over-ceiling domain is not an HTTP error on create. It shows up as a failed task. Errors lists every error the API returns.

Endpoints