> ## Documentation Index
> Fetch the complete documentation index at: https://wiki.darknetsearch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Watch look-alike domains and read alerts

> Turn on scan-wide monitors, put monitors on discovered look-alike domains, and read, filter and mark the look-alike alerts they raise in one organization-wide inbox.

A [domain scan](https://wiki.darknetsearch.com/api/guides/domain-monitoring-scans.md) finds look-alikes of `acme.com` at one point in time. Monitors keep watching after the scan and raise a look-alike alert when something changes. There are two kinds:

* **Scan-wide monitors** cover a whole scan. They alert when new look-alikes appear, or when a variation of your domain gets name servers.
* **Per-domain monitors** cover one discovered look-alike, such as `acme-login.com`. They alert on DNS records, open web ports, phishing databases, risk score, page content and spoofing of your brand.

Every alert lands in one inbox for your organization. You read it, filter it and mark alerts seen through the API. Domain monitoring appears as the **SpoofGuard** tag in the API reference. In the dashboard, the inbox is **Lookalike Domains → Alerts**.

> [!NOTE]
>
> These are not the [monitors](https://wiki.darknetsearch.com/api/guides/monitoring-rules.md) of the Alert System, whose results are matches. Look-alike monitors do not use your Monitored Assets capacity, and look-alike alerts do not go through your [delivery settings](https://wiki.darknetsearch.com/api/guides/monitoring-delivery.md).

**Availability:** Domain Monitoring, the plan feature that also opens domain scans.

**Cost:** no metered allowance. Look-alike monitors use no Monitored Assets slots. Each call counts toward the per-second [rate limit](https://wiki.darknetsearch.com/api/guides/rate-limits.md) and, when it succeeds, uses one unit of your monthly API Calls allowance.

Without Domain Monitoring, or when your license is not active, every endpoint on this page returns `403`:

```json theme={"dark"}
{
  "detail": "This feature is not included in your plan."
}
```

These endpoints have no allowance or capacity of their own, so they never return the allowance `429` or the capacity `409` described in [Plans and quotas](https://wiki.darknetsearch.com/api/guides/plans-and-quotas). Two other kinds of `429` can come back:

* **`"message": "Rate limit exceeded"`** is the per-second rate limit or your API Calls allowance. See [Rate limits](https://wiki.darknetsearch.com/api/guides/rate-limits.md).
* **`"detail": "Request was throttled. Expected available in 12 seconds."`** is the domain monitoring service's own limit of 180 requests a minute. Every API key and dashboard user of your organization shares it. Wait the seconds the message gives. The response has no `Retry-After` header.

### How alerts reach you

Look-alike alerts are not sent by email or webhook. You read them from the [alerts inbox](#read-the-alerts-inbox), and the [polling recipe](#mark-alerts-seen) below keeps an integration up to date. Monitors accept a `recipients` list, but no email is sent to those addresses.

### Watch the whole scan

Two monitors belong to the scan itself. Both are off until you turn them on. Switch them with [`analysis_update`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/analysis_detail/\{analysis_id}/):

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/analysis_detail/7c1e2d3f-5a6b-4c8d-9e0f-1a2b3c4d5e6f/ \
  -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"new_similar_domain_monitor": true, "ns_record_appears_monitor": true}'
```

| Field | Dashboard label | Alert `condition` | Alerts when |
| - | - | - | - |
| `new_similar_domain_monitor` | Watch new look-alikes | `new_similar_domain` | New domains that resemble yours appear in certificate-transparency logs or new domain registrations |
| `ns_record_appears_monitor` | Watch domain activation | `ns_record_change` | A variation of your domain that the scan generated gets name-server (NS) records, a sign that someone registered it |

Send `false` to turn one off. [`analysis_detail`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_detail/\{analysis_id}/) returns both fields with their current state. Scan-wide monitors do not appear in the monitor list. One alert from them can cover several domains, listed in its `result_domains`.

### Monitor a discovered domain

Pick look-alikes from the scan's results and send them with the conditions to watch to [`create_analysis_monitor`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/POST/api/service/create_analysis_monitor/\{analysis_id}/):

| Field | Required | Meaning |
| - | - | - |
| `domains` | Yes | Look-alikes from the scan's results. Each one gets its own monitor. |
| `conditions` | Yes | Condition codes from the table below |
| `enabled` | No | `true` by default |
| `recipients` | No | Stored with the monitor. No email is sent to these addresses. |

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/create_analysis_monitor/7c1e2d3f-5a6b-4c8d-9e0f-1a2b3c4d5e6f/ \
  -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["acme-login.com"], "conditions": ["a_record_change", "port_change", "phishing_status", "is_spoofing"]}'
```

The call returns `201` with a list of the monitors on those domains. Each one carries its `uid`, `domain`, `analysis_id`, `conditions`, `enabled`, `recipients` and timestamps. The list can also hold monitors you paused or deleted on those domains before, so pick the new one by `created_at`. Keep its `uid` to change or delete the monitor.

| Condition | Name | Alerts when | Default severity |
| - | - | - | - |
| `a_record_change` | A Record Appears | The domain gets an A record (an IP address) | Low |
| `mx_record_change` | MX Record Appears | The domain gets a mail server (MX) record | Low |
| `port_change` | New Open Port 80/443 Appears | Port 80 or 443 opens on the domain | Low |
| `phishing_status` | Website appears in a Phishing DB | The domain is listed in a phishing database | Critical |
| `urlscore_risk_change` | URLScore Risk Score Changed | The domain's URLScore risk score changes | Medium |
| `content_change` | Website Content Changed | The page content changes. Timestamps, counters and session values are ignored. | Low |
| `is_spoofing` | Website is Spoofed | The website shows your logo or brand keywords | Critical |
| `content_change_and_spoof` | Website Content Changed and Spoofed | The content changes and the site now imitates your brand | Critical |

Three rules decide which conditions make sense for a domain:

* **A, MX and port conditions alert only when something first appears.** On a domain that already has an A record, an MX record, or both web ports open, that condition never fires. Read `a_record`, `mx_record`, `http_open` and `https_open` on the scan result first.
* **Spoofing conditions need a logo or brand keywords on the scan.** Without one, `create_analysis_monitor` refuses `is_spoofing` and `content_change_and_spoof` with `400`. `monitor_update` does not check, so attach a logo or keywords before you add a spoofing condition to an existing monitor. [Set up a brand library](https://wiki.darknetsearch.com/api/guides/domain-monitoring-brand-library.md) shows how to attach them.
* **One active monitor per domain.** A domain that already has an enabled monitor returns `400` and lists the domain in `domains`. A monitor you deleted while it was enabled still counts. To resume a paused monitor, send `"enabled": true` to `monitor_update` instead of creating a new one.

### Change, pause or delete a monitor

[`monitor_update`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/monitor_update/\{monitor_id}/) takes three fields:

* `enabled`: required. It is applied on every update, so send `true` to keep the monitor running while you change something else.
* `conditions`: replaces the list of conditions.
* `recipients`: replaces the list of addresses.

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/monitor_update/4a3b2c1d-0e9f-4a8b-9c7d-6e5f4a3b2c1d/ \
  -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true, "conditions": ["phishing_status", "is_spoofing", "content_change_and_spoof"]}'
```

The call returns a one-item list with the updated monitor. Send `{"enabled": false}` to pause a monitor. A paused monitor keeps its alerts.

[`monitor_delete`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/DELETE/api/service/monitor_delete/\{monitor_id}/) returns `204`. It removes the monitor and its alerts from the inbox. Deleting a scan does the same for all of its monitors.

A monitor deleted while enabled keeps blocking its domain: `create_analysis_monitor` refuses that domain with `400` afterwards. To stop alerts for a while, pause the monitor instead. If you may want to watch the domain again, pause the monitor before you delete it.

Monitors also set the triage status of the domain in the scan's results. Creating or enabling a monitor sets it to `monitoring`. Pausing or deleting the monitor sets it to `reviewed`.

### List monitors

[`analysis_monitors`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_monitors/\{analysis_id}/) lists the per-domain monitors of one scan, newest first:

| Parameter | Meaning |
| - | - |
| `page` | 1-based page number |
| `page_size` | 10 by default, 100 at most |
| `enabled` | `true` lists only enabled monitors |
| `alerts_sort` | `desc` lists the monitors with the most alerts first, `asc` the fewest |

The response has `count`, `next`, `previous` and `results`. Raise `page` until `next` is `null`.

[`monitor_detail`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/monitor_detail/\{monitor_id}/) returns one monitor.

### Read the alerts inbox

[`alerts_list`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/alerts/) returns every look-alike alert of your organization, across all scans and monitors, newest first:

```bash theme={"dark"}
curl -G https://client-api.leak.center/api/service/alerts/ \
  -H "X-API-Key: YOUR_API_KEY" \
  --data-urlencode "seen=false" \
  --data-urlencode "severity=Critical" \
  --data-urlencode "page_size=100"
```

| Parameter | Meaning |
| - | - |
| `page`, `page_size` | Pages of 10 alerts by default, 100 at most |
| `analysis_id` | Alerts of one scan |
| `monitor_id` | Alerts of one monitor |
| `result_domain` | Alerts about one look-alike, matched exactly and ignoring case |
| `domain` | Alerts whose monitor's domain contains this text |
| `type` | One condition code, such as `phishing_status` |
| `severity` | `Critical`, `High`, `Medium` or `Low` |
| `seen` | `false` for unread alerts, `true` for alerts already marked seen |
| `history` | `true` returns the content and spoofing alerts of one scan, oldest first, for a screenshot timeline. Needs `analysis_id`. |

Leave out `date_sort`: the default order is newest first.

```json theme={"dark"}
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "uid": "e5d4c3b2-a1f0-4e9d-8c7b-6a5f4e3d2c1b",
      "domain": "acme-login.com",
      "monitor_id": "4a3b2c1d-0e9f-4a8b-9c7d-6e5f4a3b2c1d",
      "analysis_id": "7c1e2d3f-5a6b-4c8d-9e0f-1a2b3c4d5e6f",
      "condition": "is_spoofing",
      "severity": "Critical",
      "message": "The brand has been spoofed. The logo has been spoofed.",
      "result_domains": ["acme-login.com"],
      "seen": false,
      "created_at": "2026-10-08T06:00:12.403917Z"
    }
  ],
  "alert_type_counts": {
    "is_spoofing": 1,
    "phishing_status": 1
  }
}
```

The example above is shortened. Each alert carries these fields:

| Field | Meaning |
| - | - |
| `uid` | The alert's ID, used to mark it seen |
| `condition` | The condition code that fired |
| `severity` | `Critical`, `High`, `Medium` or `Low` |
| `domain` | The domain the alert is about |
| `result_domains` | Every domain the alert covers. Scan-wide monitors can list several. |
| `message` | A one-line summary |
| `change_detail` | The change as structured data. Older alerts return an empty object. |
| `screenshot_link`, `detected_logo_link` | The page screenshot and the detected logo, when the check captured them |
| `branding_keywords`, `detected_keywords` | Your keywords, and the ones found on the page |
| `seen` | Whether the alert has been marked seen |
| `monitor_id`, `analysis_id` | The monitor and scan that raised it |

`alert_type_counts` counts the alerts per condition across every page of the filtered set. `full_message` is kept for older integrations: read `change_detail` instead. Raise `page` until `next` is `null`.

[`monitor_alerts`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/monitor_alerts/\{monitor_id}/) returns the 10 newest alerts of one monitor, with the total in `count`. To page through all of them, call the inbox with `monitor_id`.

### Mark alerts seen

Send the alert `uid` values and `seen` to [`alerts_update_seen`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/alerts/):

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/alerts/ \
  -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"alert_ids": ["e5d4c3b2-a1f0-4e9d-8c7b-6a5f4e3d2c1b"], "seen": true}'
```

`seen` is required: send `true` to mark alerts seen, `false` to mark them unseen. The call returns the updated alerts as a list. IDs that are valid UUIDs but do not exist are skipped. Send only alert `uid` values: an ID that is not a UUID returns `502`. The seen state belongs to your organization, so the dashboard's Alerts tab shows the same state.

To process new alerts on a schedule:

**1. Fetch unread alerts**

Call the inbox with `seen=false` and `page_size=100`.

**2. Process them**

Handle each alert in your own system, using `condition`, `severity` and `result_domains`.

**3. Mark them seen**

Send their `uid` values with `"seen": true`.

**4. Repeat until the inbox is empty**

Fetch page 1 again until `count` is `0`. Alerts you mark seen leave the `seen=false` set, so the next unread alerts are always on page 1.

Each round uses two requests per 100 alerts. Keep the loop under the domain monitoring service's limit of 180 requests a minute, which your whole organization shares with the dashboard.

### Read one alert

[`alert_detail`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/alert_detail/\{alert_id}/) returns one alert by its `uid`, as a one-item list. Read the alert from index `0`.

### Errors

Errors from the API itself carry `detail`. Errors from the domain monitoring service carry `details`, except its own `429`, which carries `detail`. The per-second rate limit and the API Calls allowance carry `message`. Read the first of `detail`, `details` and `message` that the body contains. Every status is explained once in [Handle API errors](https://wiki.darknetsearch.com/api/guides/errors.md).

| Status | When | Body |
| - | - | - |
| `400` | A condition code is not one of the eight per-domain conditions | `{"details": "The following conditions are not valid choices: whois_change."}` |
| `400` | A domain already has an enabled monitor, or had one that you deleted while it was enabled | `{"details": "The following domains are already being monitored.", "domains": ["acme-login.com"]}` |
| `400` | `create_analysis_monitor` with a spoofing condition on a scan with no logo or brand keywords | `{"details": "Either a logo or some brand keywords need to be provided for the spoofing check."}` |
| `400` | `monitor_update` without `enabled` | `{"enabled": ["This field is required."]}` |
| `400` | `monitor_update` or `monitor_delete` with an unknown monitor | `{"details": "No monitors with the given uids exist."}` or `{"details": "No monitors with the given ID exist."}` |
| `400` | `history=true` without `analysis_id` | `{"history": ["analysis_id is required when history is true."]}` |
| `400` | Marking seen when none of the IDs exist | `{"details": "No alerts with the given uids exist."}` |
| `400` | `alert_detail` with an unknown alert | `{"details": "None of the alerts with the provided IDs exist."}` |
| `403` | Your plan lacks Domain Monitoring, or your license is not active | `{"detail": "This feature is not included in your plan."}` |
| `404` | An unknown scan or monitor in the path or in a filter | `{"details": "Analysis with this ID does not exist."}` or `{"details": "Monitor with this ID does not exist."}` |
| `404` | A path ID that is not a UUID | — |
| `429` | The domain monitoring service's limit of 180 requests a minute for your organization | `detail` starts with `Request was throttled. Expected available in`, then the wait in seconds |
| `429` | The per-second rate limit or the API Calls allowance | `{"message": "Rate limit exceeded", ...}`. See [Rate limits](https://wiki.darknetsearch.com/api/guides/rate-limits.md). |
| `502` | The domain monitoring service failed, or `alerts_update_seen` got an ID that is not a UUID | `{"detail": "The requested service is temporarily unavailable."}` |
| `504` | The domain monitoring service timed out | `{"detail": "The requested service timed out."}` |

### Endpoints

| Action | Endpoint |
| - | - |
| Turn scan-wide monitors on or off | [`PATCH /api/service/analysis_detail/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/analysis_detail/\{analysis_id}/) |
| Create monitors for discovered domains | [`POST /api/service/create_analysis_monitor/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/POST/api/service/create_analysis_monitor/\{analysis_id}/) |
| List a scan's monitors | [`GET /api/service/analysis_monitors/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_monitors/\{analysis_id}/) |
| Get a monitor | [`GET /api/service/monitor_detail/{monitor_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/monitor_detail/\{monitor_id}/) |
| Change or pause a monitor | [`PATCH /api/service/monitor_update/{monitor_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/monitor_update/\{monitor_id}/) |
| Delete a monitor | [`DELETE /api/service/monitor_delete/{monitor_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/DELETE/api/service/monitor_delete/\{monitor_id}/) |
| Get a monitor's newest alerts | [`GET /api/service/monitor_alerts/{monitor_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/monitor_alerts/\{monitor_id}/) |
| Read the alerts inbox | [`GET /api/service/alerts/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/alerts/) |
| Mark alerts seen or unseen | [`PATCH /api/service/alerts/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/alerts/) |
| Get one alert | [`GET /api/service/alert_detail/{alert_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/alert_detail/\{alert_id}/) |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.