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 — by id, by entity, or in bulk by filtering the alert list.

What you'll do

  1. Authenticate (see Authentication).
  2. Look the alert up by id or by entity, or list alerts filtered by queue_state.
  3. Read the queue_state field on the response.

The examples below show the organization-wide auth mode (x-api-key only). For the user-specific mode, also send x-user-api-key (and x-organization-code if your user belongs to multiple organizations) — see Authentication.

Get a single alert by id

The id returned from POST /v1/alert is the most reliable handle. GET /v1/alert requires exactly one of id or entity as a query parameter — passing both, or neither, returns 400 Bad Request.

cURL

curl --request GET \
  --url "https://api.doppel.com/v1/alert?id=ACM-1234" \
  --header "x-api-key: <YOUR_ORG_API_KEY>"

Python

import requests

response = requests.get(
    "https://api.doppel.com/v1/alert",
    headers={"x-api-key": "<YOUR_ORG_API_KEY>"},
    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/v1/alert");
url.searchParams.set("id", "ACM-1234");

const response = await fetch(url, {
  headers: { "x-api-key": "<YOUR_ORG_API_KEY>" },
});
const alert = await response.json();
console.log(alert.queue_state, alert.entity_state);

Look an alert up by entity

If you don't have an id, look the alert up by entity (URL or phone number). URL-encode the value.

curl --request GET \
  --url "https://api.doppel.com/v1/alert?entity=https%3A%2F%2Fsuspicious-site.example.com" \
  --header "x-api-key: <YOUR_ORG_API_KEY>"
response = requests.get(
    "https://api.doppel.com/v1/alert",
    headers={"x-api-key": "<YOUR_ORG_API_KEY>"},
    params={"entity": "https://suspicious-site.example.com"},
)
const url = new URL("https://api.doppel.com/v1/alert");
url.searchParams.set("entity", "https://suspicious-site.example.com");

const response = await fetch(url, {
  headers: { "x-api-key": "<YOUR_ORG_API_KEY>" },
});

List alerts by queue state

To check status across many alerts at once — for example, to see everything waiting on takedown — use GET /v1/alerts with a queue_state filter:

curl --request GET \
  --url "https://api.doppel.com/v1/alerts?queue_state=actioned&page_size=100" \
  --header "x-api-key: <YOUR_ORG_API_KEY>"
response = requests.get(
    "https://api.doppel.com/v1/alerts",
    headers={"x-api-key": "<YOUR_ORG_API_KEY>"},
    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/v1/alerts");
url.searchParams.set("queue_state", "actioned");
url.searchParams.set("page_size", "100");

const response = await fetch(url, {
  headers: { "x-api-key": "<YOUR_ORG_API_KEY>" },
});
const { alerts } = await response.json();

GET /v1/alerts is paginated (page is zero-indexed; default page_size is 30, maximum 200). Per the V1 OpenAPI spec, the listing response uses last_activity_timestamp, while a single-alert response uses last_activity.

The full set of documented query parameters on GET /v1/alerts (per the V1 OpenAPI spec) includes search_key, queue_state, product, created_before, created_after, last_activity_timestamp, sort_type, sort_order, page, page_size, and tags. See the Get Alerts entry in the V1 API reference for full details.

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 V1 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 V1 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_down is shown as Resolved in the Doppel Vision app (per the V1 OpenAPI spec note).
  • actioned is 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 V1 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/v1/alert",
            headers={"x-api-key": "<YOUR_ORG_API_KEY>"},
            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

StatusMeaning
200 OKAlert (or alert list) returned successfully.
400 Bad RequestBoth or neither of id / entity was provided to GET /v1/alert, or another query parameter was malformed.
401 UnauthorizedMissing or invalid auth headers.
404 Not FoundNo alert in your organization matches the supplied id or entity. (Single-alert endpoint only.)
429 Too Many RequestsRate limit exceeded.

Next steps