Check the status of an alert
Check the status of an alert
After you submit an alert, Doppel processes the entity through
its triage workflow. This guide shows how to read an alert's current state from
the API — either for a single alert by id, or in bulk with server-side list
filters.
What you'll do
- Get an OAuth access token (see Authentication).
- Look the alert up by
id, or filter the alert list. - Read the
queue_statefield on the response.
Get a single alert by id
The id returned from POST /v2/alert is the handle for follow-up status checks. GET /v2/alert requires the id query parameter.
cURL
curl --request GET \
--url "https://api.doppel.com/v2/alert?id=ACM-1234" \
--header "Authorization: Bearer <YOUR_ACCESS_TOKEN>"Python
import requests
response = requests.get(
"https://api.doppel.com/v2/alert",
headers={"Authorization": f"Bearer {access_token}"},
params={"id": "ACM-1234"},
)
response.raise_for_status()
alert = response.json()
print(alert["queue_state"], alert["entity_state"])Node.js
const url = new URL("https://api.doppel.com/v2/alert");
url.searchParams.set("id", "ACM-1234");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${access_token}` },
});
const alert = await response.json();
console.log(alert.queue_state, alert.entity_state);Filter the alert list
To check status across many alerts at once — for example, to see everything waiting on takedown — use GET /v2/alerts with a queue_state filter:
curl --request GET \
--url "https://api.doppel.com/v2/alerts?queue_state=actioned&page_size=100" \
--header "Authorization: Bearer <YOUR_ACCESS_TOKEN>"response = requests.get(
"https://api.doppel.com/v2/alerts",
headers={"Authorization": f"Bearer {access_token}"},
params={"queue_state": "actioned", "page_size": 100},
)
for alert in response.json()["alerts"]:
print(alert["id"], alert["entity"], alert["last_activity_timestamp"])const url = new URL("https://api.doppel.com/v2/alerts");
url.searchParams.set("queue_state", "actioned");
url.searchParams.set("page_size", "100");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${access_token}` },
});
const { alerts } = await response.json();queue_state also accepts a comma-separated list. V2 provides these additional
multi-value filters:
| Parameter | What it matches |
|---|---|
brand_ids | The alert's original brand UUID |
severity | high, medium, or low |
entity_state | The entity states listed under Reading the response |
platform | Platform enum values |
modules | Alert modules, such as domains, social_media, paid_ads, mobile_apps, ecommerce, email, telco, darkweb |
platforms | Detection platform subtype names, the same values the Doppel Vision alert list platform filter uses |
tag_ids / excluded_tag_ids | Tag UUIDs the alert must include / must not include |
uploader_ids / assignee_ids | Uploader or assignee user UUIDs |
sources | Alert source categories, such as abuse_box, doppel_api, pivot, domains_feed |
Within one parameter, an alert matches if it matches any supplied value. You can
combine parameters to narrow the result set:
curl --request GET \
--url "https://api.doppel.com/v2/alerts?queue_state=actioned,needs_confirmation&severity=high,medium&platform=domains" \
--header "Authorization: Bearer <YOUR_ACCESS_TOKEN>"V2 also accepts the single-value filters available in the Doppel Vision alert
lists. Use search for broad alert search across display URLs and other
indexed alert text; the existing search_key parameter keeps its entity
substring behavior. product_surface (brand_protection or
executive_protection) and is_dark_web select the product surface and
dark-web scope. If you omit is_dark_web, the response includes dark-web
alerts only when Dark Web is enabled for your organization. Set
is_dark_web=false to exclude dark-web alerts. Set is_dark_web=true to
return only dark-web alerts. Set it to true when you use a dark-web filter.
sourced_by (customer or doppel), has_preview,
has_connected_alerts, include_doppel_uploaders, and
include_unassigned_assignee refine the uploader, preview, and assignee
filters. Module-specific filters cover domain alerts (tld, ip_address,
registration_countries), telco alerts (carriers), paid-ad alerts
(advertiser_names, advertiser_verifications), and dark-web alerts
(dark_web_networks, dark_web_sources, dark_web_leak_name,
dark_web_machine_name, dark_web_crawled_after, dark_web_crawled_before,
dark_web_leak_contents, show_only_parsed, organization_email_leaks,
dark_web_exposure_types, and the dark_web_password_* and
dark_web_username_* constraints). Parameter types and enum values are listed
on the List Alerts entry in the V2 API reference.
GET /v2/alerts is paginated. page is zero-indexed. The default
page_size is 30. The maximum page_size is 200.
Only the first 50,000 results of a search can be paged through. The request
returns 422 Unprocessable Entity with code set to
result_window_exceeded, a message, and maximum_results set to 50000
in two cases: when page and page_size together address a position at or
beyond the 50,000th result (any search), or when a search filtered by
last_activity_timestamp, last_activity_before, created_after, or
created_before matches more than 50,000 alerts (returned on page 0). Narrow
the time range and retry; the limit cannot be paged past. A page-0 request
with no time filter is always served, however many alerts your organization
has, so connectivity checks and first-page reads do not depend on tenant size.
Use last_activity_timestamp as the start of a last-activity range. Use
last_activity_before as the end of the range. Both limits are inclusive.
Use sort_type=last_actioned_at to sort by the most recent enforcement action.
Use sort_type=last_activity to sort by the most recent alert activity. The
list can also be sorted by date_sourced (creation time, the default),
display_url, last_reported_at, last_resolved_at, or severity. You
must also send sort_order=asc or sort_order=desc.
date_last_actioned is a legacy alias for last_activity. Do not use this
alias for a new integration.
Each alert contains a maximum of 100 recent audit log entries by default. Set
audit_log_limit from 0 through 200 to change this limit. Check
audit_logs_truncated to determine if the response does not contain older
entries.
To synchronize or discover alerts without loading snapshots, audit logs, tags,
summaries, or screenshot data, send detail_level=basic. Each alert in a basic
response contains only id, entity, queue_state, entity_state,
severity, product, created_at, and last_activity_timestamp. Omit
detail_level (or send detail_level=full) to receive the standard alert
response. The full alert object contains brand and brand_id. brand is
the brand name. brand_id is the brand UUID. The basic alert object does not
contain these fields.
curl --request GET \
--url "https://api.doppel.com/v2/alerts?queue_state=actioned&detail_level=basic" \
--header "Authorization: Bearer <YOUR_ACCESS_TOKEN>"The listing response uses last_activity_timestamp. A single-alert response
uses last_activity.
Reading the response
The status of an alert is captured by two fields:
queue_state— where the alert sits in Doppel's workflow. Per the V2 OpenAPI spec, the value is one of:doppel_review,needs_confirmation,actioned,taken_down,monitoring,archived.entity_state— the live state of the entity (URL, phone, etc.) the alert is tracking. Per the V2 OpenAPI spec, the value is one of:active,down,parked,suspicious,unclassified,unrelated,related,unknown.
Two queue_state values map directly to UI actions in Doppel Vision:
taken_downis shown as Resolved in the Doppel Vision app (per the V2 OpenAPI spec note).actionedis the value set when Request Takedown is invoked in the UI (see Request a takedown).
For the semantics of the other values, see the Get Alert entry in the V2 API reference.
Polling pattern
If you poll for status, do it on a backoff and stop once queue_state is taken_down or archived:
import time
TERMINAL_STATES = {"taken_down", "archived"}
def wait_for_resolution(alert_id: str, timeout_seconds: int = 86400) -> dict:
deadline = time.time() + timeout_seconds
delay = 60
while time.time() < deadline:
response = requests.get(
"https://api.doppel.com/v2/alert",
headers={"Authorization": f"Bearer {get_token()}"},
params={"id": alert_id},
)
response.raise_for_status()
alert = response.json()
if alert["queue_state"] in TERMINAL_STATES:
return alert
time.sleep(delay)
delay = min(delay * 2, 900)
raise TimeoutError(f"{alert_id} did not reach a terminal state in time")Status codes
| Status | Meaning |
|---|---|
200 OK | Alert (or alert list) returned successfully. |
401 Unauthorized | Invalid or missing JWT — refresh your access token. |
403 Forbidden | The alert does not belong to your organization, or your token is not mapped to an organization. |
404 Not Found | No alert in your organization matches the supplied id. (Single-alert endpoint only.) |
422 Unprocessable Entity | The requested page lies at or beyond the 50,000-result window, or a time-filtered search matches more than 50,000 alerts (code: result_window_exceeded, maximum_results: 50000). Narrow the time range and retry. (Alert-list endpoint only.) |
429 Too Many Requests | Rate limit exceeded — see the Retry-After header. |
Next steps
- Request a takedown — set an alert's
queue_statetoactionedviaPUT /v2/alert. - Submit a new alert — start tracking a new entity.
Updated 7 days ago
