Stealer
Search device records for credentials, cookies, and saved logins captured from compromised machines. Every plan can inspect the file-archive browser; below Premium its structure and counts are real and its values are masked. Row masking is per record, so a row the caller has unlocked reads in full on a plan that masks by default.
POST /stealer/search
Search stealer logs
Query device records for hits on the given identifier. Every plan gets the same page of 100 rows. Free and Pro mask the credential values by default, Premium and Team return them, and the top-level masked says which of the two this plan is.
Masking is applied per record, not per response: a masked: true page still returns real values for any row this caller has unlocked, so a single page can mix the two. Branch on each row's unlocked flag. Rows also carry record_id, which is what an unlock is spent against.
What you send.
JSON body, required.
type string required
One of email, username, domain, password, ip, email_domain
term string required
offset integer default 0
first_seen_only boolean default false
Admin-granted feature. Sort oldest-first so clients can retain the first row for each host/login/password credential.
What comes back.
200 Device-record hits. `masked` reports the plan default; each row's `unlocked` flag reports whether that row is masked in fact.
Successful response.
maskedsays whether this plan masks device values by default:trueon free and Pro,falseon Premium and Team.Masking is applied per record, not per response. A
masked: truepage still returns real values for any row this caller has unlocked, so branch on each row'sunlockedflag rather than on the top-level one.success boolean required
data one of
One of these.
1 object
Response from a plan that does not mask by default.
count integer
results array of object
Open row shape. Two named properties are called out because integrators need them to drive unlocks.
record_id string
Stable id for this device record - the provider's
stealerlog_id.unlocked boolean
Whether this caller has already revealed this record.
Other keys may also be present.
pagination object
Open object, with no fixed keys.
plan_id string
Starter is a retired legacy id and is not a checkout target.
One of free, starter, professional, premium, team
masked boolean
first_seen_only boolean
unlocks integer
Record unlocks spent in the current unlock period.
unlocks_limit integer
Unlock allowance for the current unlock period, which resets weekly.
0means the plan has no unlock mechanism at all, which is every paid tier.response_time_ms integer
2 object
Response from a plan that masks by default (free and Pro).
count integer
results array of object
Masked value shape returned by a plan that masks device values by default (free and Pro). Premium and Team get the same row structure with real values, and so does any single row this caller has unlocked, so one page can mix masked and unmasked rows.
record_id string
Stable id for this device record - the provider's
stealerlog_id. Present on every plan; pass it toPOST /unlocksto reveal the row.unlocked boolean
Whether this caller has already revealed this record. An unlocked row carries real values even when the response says
masked: true.url string
Scheme and host retained; path masked.
origin string
country string
browser string
os string
time_ingested string, date-time
login string
Censored unless caller searched by email/username.
password_locked boolean
masked boolean
first_seen_only boolean
unlocks integer
Record unlocks spent in the current unlock period.
unlocks_limit integer
Unlock allowance for the unlock period; 5 a week on the free tier.
response_time_ms integer
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
403 The feature is granted per account by an admin rather than by plan, and this account doesn't hold the grant.
The same shape as 400.
429 An allowance was exhausted, or a per-hour cap was hit. Which allowance depends on `metering`: a pooled plan drains one `lookups` pool, while the free tier can run out on one surface with the others still open. The same code covers counters that sit on different clocks, so read `resets_at` and `unlocks_reset_at` from `GET /search/stats` to learn when the allowance you hit comes back.
The same shape as 400.
503 This surface is disabled or unreachable.
The same shape as 400.
POST /stealer/raw
Raw query - regex or wildcard (Premium and Team only)
Freeform query against device-record files with regex or wildcard syntax. Premium and Team only; every lower plan, Pro included, gets a 403 with code plan_upgrade_required before the query runs. Pick one: passing both regex: true and wildcard: true is a 400.
What you send.
JSON body, required.
query string required
offset integer default 0
regex boolean
wildcard boolean
What comes back.
200 Raw match results.
success boolean required
data object
count integer
sources integer
results array of object
Open object, with no fixed keys.
pagination object
Open object, with no fixed keys.
raw boolean
response_time_ms integer
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
403 The model-backed device tabs and raw archive search are Premium and Team only. The rest of the per-device browser opens on every plan.
The same shape as 400.
429 An allowance was exhausted, or a per-hour cap was hit. Which allowance depends on `metering`: a pooled plan drains one `lookups` pool, while the free tier can run out on one surface with the others still open. The same code covers counters that sit on different clocks, so read `resets_at` and `unlocks_reset_at` from `GET /search/stats` to learn when the allowance you hit comes back.
The same shape as 400.
503 This surface is disabled or unreachable.
The same shape as 400.
GET /stealer/file/{id}/tree
File-archive directory tree
In the URL.
id in path string required
Stealer-log file identifier.
What comes back.
200 Opaque tree structure, available on every plan.
success boolean required
data object
Open object, with no fixed keys.
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
429 Too many distinct stealer logs opened within one clock hour. Re-opening a log already touched in the same hour does not count against it.
The same shape as 400.
503 This surface is disabled or unreachable.
The same shape as 400.
GET /stealer/file/{id}/export
Download a whole stealer log as a ZIP
Streams a ZIP mirroring the original archive structure - every file under the upstream tree - plus a _metadata.json sidecar carrying the structured tab data. Gated on the per-account export grant, which an admin issues; plan tier is deliberately not a gate, so this is the one by-id file route that is not Premium-only.
The response is streamed, so headers go out before the upstream fetches finish. A fetch that fails partway does not fail the call: the ZIP still completes and _metadata.json records what was missed under file_errors.
Ceilings, all recorded in _metadata.json rather than raised as errors: 5000 files from the tree, 10 MiB per file, 200 MiB per bundle. Each distinct log counts against the same hourly file-access cap as the read routes.
In the URL.
id in path string required
Stealer-log file identifier.
What comes back.
200 ZIP archive, sent as `Content-Type: application/zip` with a `Content-Disposition: attachment` filename of `stealer-log-{id}.zip`.
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
403 The feature is granted per account by an admin rather than by plan, and this account doesn't hold the grant.
The same shape as 400.
429 Too many distinct stealer logs opened within one clock hour. Re-opening a log already touched in the same hour does not count against it.
The same shape as 400.
503 This surface is disabled or unreachable.
The same shape as 400.
GET /stealer/file/{id}/path/{path}
Read a file from the archive
Available on every plan. Below Premium the file keeps its real path, byte count, line count and line breaks, while every content character is masked. The response carries masked: true in that case.
In the URL.
id in path string required
path in path string required
Slash-separated path inside the archive (e.g.
Soft/Chrome/Login Data.txt)...segments are rejected.
What comes back.
200 File contents. Either the parsed JSON payload, or a `{path, content, size, masked}` object for raw text files.
success boolean required
data one of
One of these.
1 object
path string
content string
size integer
2 object
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
429 Too many distinct stealer logs opened within one clock hour. Re-opening a log already touched in the same hour does not count against it.
The same shape as 400.
503 This surface is disabled or unreachable.
The same shape as 400.
GET /stealer/file/{id}/{tab}
Browse a tab on a stealer-log file (read-only tabs)
Available on every plan. Free and Pro receive the same keys, row counts and totals with sensitive leaf values masked; Premium and Team receive the values. ai_analysis and ai_chat are the exceptions: those two model-backed tabs return 403 plan_upgrade_required below Premium, and an unlock does not open them - each is a paid language-model call with no censored form to serve, so there is nothing a unit could buy. Some tabs are GET-only (system, accounts, software, phrases, payments, raw). For paginated tabs use POST and pass filter, limit and offset in the body.
In the URL.
id in path string required
tab in path string required
One of credentials, cookies, autofills, system, accounts, software, corporate, phrases, payments, browser_history, raw, search, ai_analysis, ai_chat
What comes back.
200 Opaque tab payload.
success boolean required
data object
Open object, with no fixed keys.
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
403 The model-backed device tabs and raw archive search are Premium and Team only. The rest of the per-device browser opens on every plan.
The same shape as 400.
429 Too many distinct stealer logs opened within one clock hour. Re-opening a log already touched in the same hour does not count against it.
The same shape as 400.
503 This surface is disabled or unreachable.
The same shape as 400.
POST /stealer/file/{id}/{tab}
Browse a tab with filters
Same value-access rule as the GET form: full structure on every plan, masked values below Premium, with ai_analysis and ai_chat still gated and still out of reach of an unlock. Use this for paginated or filterable tabs (credentials, cookies, autofills, browser_history, search).
In the URL.
id in path string required
tab in path string required
One of credentials, cookies, autofills, system, accounts, software, corporate, phrases, payments, browser_history, raw, search, ai_analysis, ai_chat
What you send.
JSON body, optional.
search string
Filter results by substring match.
limit integer
offset integer default 0
ignoreExpired boolean
Cookies tab only.
ignoreDuplicates boolean default true
Cookies tab only.
summary_only boolean
Browser history tab only.
entries_only boolean
Browser history tab only.
view string
Browser history tab only.
categories array of string
browsers array of string
What comes back.
200 Opaque tab payload.
success boolean required
data object
Open object, with no fixed keys.
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
403 The model-backed device tabs and raw archive search are Premium and Team only. The rest of the per-device browser opens on every plan.
The same shape as 400.
429 Too many distinct stealer logs opened within one clock hour. Re-opening a log already touched in the same hour does not count against it.
The same shape as 400.
503 This surface is disabled or unreachable.
The same shape as 400.
GET /stealer/first-seen
First time a credential surfaced
Returns the earliest device-record document that mentions the term, or null if there are no matches. Cached for 24h server-side and available on every plan; sensitive values inside the document are masked below Premium while the date and source name remain readable.
In the URL.
type in query string required
One of email, username, domain, password, ip, email_domain
term in query string required
What comes back.
200 First-seen document or null.
success boolean required
data one of
One of these.
1 null
2 object
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
503 This surface is disabled or unreachable.
The same shape as 400.
GET /stealer/source/{id}
Source metadata for one log
Summary metadata for a single device record, for callers that arrive at a log by id without having gone through a search first. Available on every plan and cached server-side for 24h. Sensitive values are masked below Premium; data is null when the id resolves to nothing.
In the URL.
id in path string required
Stealer-log file identifier.
What comes back.
200 Source metadata, or null.
success boolean required
data one of
One of these.
1 null
2 object
400 The request was malformed or invalid.
success boolean required
error string required
code string
Machine-readable error tag. Omitted whenever it is empty, which is most generic errors, so branch on status too.
One of quota_exceeded, hourly_limit, file_access_limit, plan_upgrade_required, upgrade_required, feature_not_enabled, email_verification_required, monitor_limit, monitor_surface_not_allowed, monitor_first_seen_not_allowed, monitor_webhook_invalid, monitor_webhook_not_allowed, monitor_webhook_key_required
429 Too many distinct stealer logs opened within one clock hour. Re-opening a log already touched in the same hour does not count against it.
The same shape as 400.
503 This surface is disabled or unreachable.
The same shape as 400.