> ## 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.

# Scan an organization's domain for look-alikes

> Start a look-alike scan of a registered domain, follow its progress, filter and triage the registered look-alikes it finds, then change, stop, rescan, delete or export the scan.

A scan takes one domain your organization owns, such as `acme.com`, and finds its registered look-alikes. It generates candidate names, searches new domain registrations and certificate transparency logs, and looks up the DNS records of every candidate. Each candidate with name servers becomes a result. Results with a live web server then get a screenshot, a URL risk score and, when you attach them, brand keyword and logo checks.

The flow is asynchronous: start the scan, poll it while it runs, then read, filter and triage its results. The API calls a scan an *analysis*. [Monitor look-alike domains](https://wiki.darknetsearch.com/api/guides/domain-monitoring.md) explains how scans fit with the brand library, look-alike alerts and takedowns.

**Availability:** Domain Monitoring. [Plans and quotas](https://wiki.darknetsearch.com/api/guides/plans-and-quotas) lists what each plan includes.

**Cost:** no metered allowance. Starting a scan of a new domain takes one Monitored Assets slot, held until you delete the scan. Monitors draw on the same slots. Rescans, polling, results, triage and exports take no slot. Calls made with your API key count toward the API Calls allowance and the per-second rate limit described in [Rate limits](https://wiki.darknetsearch.com/api/guides/rate-limits.md). Only `2xx` responses count toward the allowance.

Every endpoint on this page returns `403` with `{"detail": "This feature is not included in your plan."}` when your plan lacks Domain Monitoring, and also when your license is not in force. `start_domain_analysis` also returns `409` when every Monitored Assets slot is in use:

```json theme={"dark"}
{
  "detail": "You have reached your Monitored Assets limit of 10.",
  "resource": "monitored_assets",
  "limit": 10
}
```

No endpoint on this page has a metered allowance, so none returns the allowance `429` with `resource` and `period`. [Monitored Assets slots](https://wiki.darknetsearch.com/api/guides/domain-monitoring.md#monitored-assets-slots) explains how to free a slot.

### Before you start

Register the domain as an asset of your organization. Call [`organization_assets_create`](https://client-api.leak.center/scalar-docs/#tag/organization-settings/POST/api/service/organization_assets_create/) with `asset_type` set to `domain` and the domain in `value`, or add it in the dashboard under **Manage** → **Assets**. Registering an asset needs a license in force.

```bash theme={"dark"}
curl -X POST https://client-api.leak.center/api/service/organization_assets_create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"asset_type": "domain", "value": "acme.com"}'
```

A subdomain such as `shop.acme.com` must be registered as its own asset before you can scan it. When its parent domain is already registered, `organization_assets_create` registers nothing and answers `200` with `"detail": "Asset is covered by an existing broader asset; nothing was created."`.

A logo, brand keywords, a word list and trusted domains make a scan check more. Create them in the brand library before you start, or attach them later. See [Set up a brand library](https://wiki.darknetsearch.com/api/guides/domain-monitoring-brand-library.md).

### Start a scan

[`start_domain_analysis`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/POST/api/service/start_domain_analysis/) needs one field, `domain`.

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/start_domain_analysis/ \
  -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "acme.com"}'
```

The call returns `200` with the new scan's ID:

```json theme={"dark"}
{
  "analysis_id": "3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63",
  "total_count": 0,
  "variations": [],
  "params": {
    "domain": "acme.com",
    "modules": [
      {"module_name": "module_tld", "module_code": "module_tld", "enabled": true}
    ],
    "config": {},
    "custom_domains": [],
    "spoofing_op": "and"
  },
  "status_message": "Analysis request accepted. Variations will be generated asynchronously."
}
```

Keep `analysis_id`. Every other call on this page takes it. `params` echoes the settings the scan runs with, and `params.modules` lists every detection module it runs. An entry for a module that is no longer offered can have `module_name` set to `null`. The list is shortened here.

The value of `domain` is cleaned before it is matched against your registered assets. A scheme, path, port, user name and trailing dot are removed, the name is lowercased, and an internationalized name is converted to its `xn--` form. `https://ACME.com/login` is read as `acme.com`.

> [!NOTE]
>
> **The scan picks its own detection modules.** A `modules` list in the body is ignored, and the call still succeeds. [`analysis_configs`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_configs/) lists the modules, the look-alike alert conditions and the default word lists, for reference.

#### Optional fields

Two of these fields add a module to the scan. The IDs come from your organization's [brand library](https://wiki.darknetsearch.com/api/guides/domain-monitoring-brand-library.md).

| Field | Type | What it adds |
| - | - | - |
| `logo_id` | integer | A logo check on every result with a web server, and the Google Lens module, a reverse image search for sites that reuse your logo. |
| `branding_id` | integer | A brand keyword check on every result with a web server. |
| `wordlist_code` | string | The word combination module, which joins your domain with each word in the list. Send the word list's `code`, not its `id`. Letters, digits, `-` and `_` only. |
| `whitelist_id` | integer | Trusted domains. Results that match the list are left out of the results and the counters. |
| `custom_domains` | array of strings | Up to 200 domains or URLs you already know about, checked along with the generated candidates. |

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/start_domain_analysis/ \
  -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "acme.com", "logo_id": 12, "branding_id": 4, "wordlist_code": "acme-products"}'
```

Without a logo or keywords, the scan still runs. `module_statuses` in the scan [says which checks did not run](#read-the-scan).

#### Start a domain you already scan

Each domain has one scan. Starting it again does not create a second one:

* **The scan has finished or was stopped.** The call returns `200` with the existing `analysis_id`, its `total_count`, and a `status_message` saying the scan is reused. Nothing reruns, and the fields you sent are not applied. To change the settings, [update the scan](#change-a-scans-settings), then [rescan](#stop-rescan-or-delete) it.
* **The scan is still `running` or `initial_completed`.** The call returns `400` with the scan's ID:

```json theme={"dark"}
{
  "details": "An active scan already exists for acme.com. Update the existing analysis settings and use the rescan endpoint, or delete the existing scan before starting a new one.",
  "analysis_id": "3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63"
}
```

#### Why a start is refused

The checks run in this order. The first one that fails answers:

1. **Plan feature.** `403`, as above.

2. **Rate limit.** `429` with `"message": "Rate limit exceeded"` when you hit the per-second rate limit or your API Calls allowance. See [Rate limits](https://wiki.darknetsearch.com/api/guides/rate-limits.md).

3. **Monitored Assets slots.** `409`. At the limit, every start is refused, even one for a domain you already scan. Use [`analysis_rescan`](#stop-rescan-or-delete) for a domain you already scan.

4. **Registered asset.** `400` when the domain is not a registered asset:

   ```json theme={"dark"}
   {
     "domain": ["'shop.acme.com' is not a registered domain asset. Subdomains must be registered as their own asset."]
   }
   ```

   A `domain` that cannot be read as a domain name at all, such as a number or an invalid internationalized name, returns `{"domain": ["Invalid value."]}`.

5. **Scanning service limit.** `429` when your organization has sent 10 start requests in the past hour, counting starts from the dashboard. The message gives the wait in seconds.

6. **Scanning service checks.** `400` with `details` when the scanning service does not accept your registered asset as a domain, when the domain is one of the 100 most visited domains on the internet, or when it already has a running scan. Also when 10 or more of your scans started within the last hour are still running, when an attachment ID is not in your brand library, or when you send more than 200 custom domains.

[Errors](#errors) quotes each message.

### Follow progress

Poll [`analysis_detail`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_detail/\{analysis_id}/) with the `analysis_id`. Send `page_size=1` while you poll, so each response carries one result. A poll every 30 seconds or slower is enough.

```bash theme={"dark"}
curl -G https://client-api.leak.center/api/service/analysis_detail/3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63/ \
  -H "X-API-Key: YOUR_API_KEY" \
  --data-urlencode "page_size=1"
```

```json theme={"dark"}
{
  "domain": "acme.com",
  "status": "initial_completed",
  "uid": "3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63",
  "created_at": "2026-10-08T09:12:44.512000Z",
  "updated_at": "2026-10-08T09:31:07.201000Z",
  "total_variations": 4210,
  "total_initial_done": 4210,
  "total_async": 37,
  "total_async_done": 25,
  "total_async_remaining": 12,
  "async_done": false,
  "total_detected_domains": 96
}
```

The response is shortened here. A scan moves through these states:

| `status` | What is happening | What to read |
| - | - | - |
| `running` | Candidates are generated and their DNS records looked up. Results appear as they are found. | `total_initial_done` counts up to `total_variations`. |
| `initial_completed` | Every candidate is looked up. Results with a web server get their screenshot, URL score and spoofing checks. | `total_async_remaining` counts down to `0`. `total_async` is the number of results with a web server. |
| `completed` | Every check is done. | `async_done` is `true`. |
| `stopped` | You stopped the scan. Queued lookups and checks are skipped. | The results found so far stay readable. |

Results are readable in every state, and counters grow while the scan runs. The response also carries the first page of results, with `page`, `page_size`, `total_items` and `total_pages`.

### Read the scan

The same call returns the scan's summary and one page of results.

#### The summary

| Field | Meaning |
| - | - |
| `total_detected_domains` | Results, without the ones your trusted domains hide. |
| `total_webservers`, `total_http_open`, `total_https_open` | Results with a web server, with HTTP open, and with HTTPS open. |
| `total_a_records`, `total_mx_records` | Not a count of results with a record. A missing record reads `N/A` and is still counted. To count results with an A or MX record, filter with `a_record=true` or `mx_record=true` and read `total_items`. |
| `total_brand_spoofing`, `total_logo_spoofing` | Results where the brand keyword check or the logo check matched. |
| `enumeration_techniques` | Results per discovery method, each with `module_name`, `module_code` and `count`. Use `module_code` to [filter](#filter-and-sort-results). |
| `module_statuses` | The checks that did not run, and why. See below. |
| `logo`, `branding`, `whitelist`, `whitelisted_domains` | The attached logo, keyword set and trusted-domain list, and the results the list hides. |
| `full_scan` | `true` when both a logo and a keyword set are attached. |
| `ns_record_appears_monitor`, `new_similar_domain_monitor`, `monitors` | The scan-wide look-alike monitors and the look-alike monitors on this scan. See [Watch look-alike domains and read alerts](https://wiki.darknetsearch.com/api/guides/domain-monitoring-alerts.md). |

`module_statuses` names each check that was skipped because nothing was attached:

```json theme={"dark"}
{
  "module_statuses": {
    "brand_spoofing": {
      "status": "not_configured",
      "reason": "branding_list_not_supplied",
      "message": "Brand Spoofing was not run because no branding keywords or branding list was supplied."
    },
    "logo_spoofing": {
      "status": "not_configured",
      "reason": "logo_not_supplied",
      "message": "Logo Spoofing was not run because no logo was supplied."
    }
  }
}
```

An empty object means both checks ran.

#### Results

Each entry in `results` is one registered look-alike. This one is shortened:

```json theme={"dark"}
{
  "id": 48211,
  "domain": "acme-login.com",
  "module_name": "Common words",
  "ns_record": "ns1.acme-login.com",
  "a_record": "203.0.113.24",
  "mx_record": "N/A",
  "http_open": true,
  "https_open": true,
  "brand_spoofing": true,
  "detected_keywords": ["acme"],
  "logo_spoofing": false,
  "is_new": false,
  "categories": ["Suspicious"],
  "domain_age": 4,
  "domain_age_category": "zero_to_one_week",
  "status": "open",
  "action_required": true
}
```

| Field | Meaning |
| - | - |
| `id` | The result's ID. [Triage](#triage-results) takes it. |
| `domain` | The look-alike domain. |
| `module_name` | How the scan found it, as a display name. |
| `ns_record`, `a_record`, `mx_record`, `dns_type` | DNS records. A missing A or MX record reads `N/A`. |
| `http_open`, `https_open`, `hosting_name` | Whether the site answers over HTTP and over HTTPS, and the hosting provider. |
| `whois`, `whois_formatted` | Registration data, raw and parsed. |
| `domain_age`, `domain_age_category` | Days since registration, and its bucket. Without a registration date, `domain_age` is `null` and `domain_age_category` is `age_unknown`. |
| `screenshot` | A link to a screenshot of the site. A failed capture links to a placeholder image. `null` while a capture is pending, and when none was taken. |
| `urlscore`, `urlscore_data` | The URL risk score and the scan behind it. `urlscore` is `null` while the check is pending, and `N/A` without a web server. |
| `phishing` | Phishing database entries for the domain. An empty object means none. |
| `brand_spoofing`, `detected_keywords`, `logo_spoofing` | The brand keyword and logo checks. Each reads `N/A` without a web server. |
| `categories` | Labels: `Suspicious` (a spoofing check matched), `Phishing`, `Parked`, `Broken`, `Blacklist` (the IP is on a blocklist) and `Uncategorized` (no other label applies). Category names assigned to the result with [`analysis_assign_categories`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/analysis_assign_categories/\{analysis_id}/) also appear. |
| `is_new` | `true` when the scan-wide monitors added the result after the first run. |
| `action_required` | `true` when the brand keyword or logo check matched. |
| `status` | The triage status. See [Triage results](#triage-results). |

#### Filter and sort results

Add filters as query parameters. Boolean filters take `true` or `false`, and apply only when you send them. Without a sort, results come in the order they were found.

| Parameter | Effect |
| - | - |
| `page`, `page_size` | `page_size` defaults to `25`. A page past the end returns an empty `results` list. |
| `domain` | Part of the look-alike's name. Several comma-separated values match those names exactly instead. |
| `domains` | Exact names, comma-separated. |
| `module_code` | A discovery method from `enumeration_techniques`. Repeat the parameter to select several. |
| `web` | `true`: the site answers over HTTP or HTTPS. `false`: it answers over neither. |
| `a_record`, `mx_record` | The result has an A record, or an MX record. |
| `has_screenshot` | A screenshot was captured. |
| `phishing` | The domain is in a phishing database. |
| `brand_spoofing`, `logo_spoofing` | The brand keyword check, or the logo check, matched. |
| `action_required` | `true`: either spoofing check matched. |
| `is_new` | The scan-wide monitors added the result after the first run. |
| `status` | A triage status, such as `open` or `reviewed`. |
| `category` | `Suspicious`, `Phishing`, `Parked`, `Broken`, `Blacklist`, `Uncategorized`, or a category name assigned to results. |
| `domain_age` | `zero_to_one_week`, `one_week_to_month`, `month_to_six_months`, `older_than_six_months` or `age_unknown`. Any other value returns `400`. |
| `registrar` | Part of the WHOIS registrar name, case-insensitive. |
| `urlscore` | Sorts by URL risk score, `asc` or `desc`. Results without a score come last. |
| `whois_creation_date_sort`, `whois_expiration_date_sort` | Sorts by WHOIS creation or expiry date, `asc` or `desc`. Results without the date come last. |

> [!WARNING]
>
> **`urlscore` sorts. It does not filter.** `urlscore=desc` returns every result, highest score first. `urlscore=N/A` returns no results at all.

This call lists the open look-alikes with a web server whose spoofing checks matched:

```bash theme={"dark"}
curl -G https://client-api.leak.center/api/service/analysis_detail/3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63/ \
  -H "X-API-Key: YOUR_API_KEY" \
  --data-urlencode "web=true" \
  --data-urlencode "action_required=true" \
  --data-urlencode "status=open" \
  --data-urlencode "page_size=50"
```

#### Count results by age and category

[`analysis_category_stats`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_category_stats/\{analysis_id}/) counts a scan's results per domain-age bucket and category, in one call. Use it to size a triage queue before you page through the results.

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/analysis_category_stats/3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63/ \
  -H "X-API-Key: YOUR_API_KEY"
```

The response is a list with one entry per bucket, always in this order: `zero_to_one_week` (under 7 days), `one_week_to_month` (7 to 29 days), `month_to_six_months` (30 to 179 days), `older_than_six_months` and `age_unknown` (no registration date).

```json theme={"dark"}
[
  {
    "domain_age_category": "zero_to_one_week",
    "domains_per_category": {
      "Parked": 1,
      "Suspicious": 2,
      "Phishing": 0,
      "Blacklist": 0,
      "Broken": 0,
      "Uncategorized": 4
    }
  }
]
```

The response is trimmed here to the first bucket. `domains_per_category` always carries the six standard categories, plus each custom category defined for your organization, even at `0`. Custom categories are the ones you assign with `analysis_assign_categories`. A result with several categories counts once in each. The counts cover every result of the scan, including those your trusted domains hide, so they can exceed what the filtered results list shows.

### Triage results

Mark a result `reviewed` once you have looked at it, with [`analysis_result_update`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/analysis_result_update/\{analysis_result_id}/) and the result's `id`:

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/analysis_result_update/48211/ \
  -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "reviewed"}'
```

The call returns `200` with an empty body. Send `open` to undo it. Then filter with `status=open` to see only what is left.

You can set only `open` and `reviewed`. Three more statuses are set for you:

| `status` | Set when |
| - | - |
| `monitoring` | An enabled look-alike monitor exists for the domain. See [Watch look-alike domains and read alerts](https://wiki.darknetsearch.com/api/guides/domain-monitoring-alerts.md). |
| `td_in_progress` | A takedown request for the domain is sent. See [Take down a look-alike domain](https://wiki.darknetsearch.com/api/guides/domain-takedowns.md). |
| `td_completed` | The takedown is completed. |

Disabling or deleting that look-alike monitor, or deleting a takedown, sets the result back to `reviewed`. A `reviewed` status is not always a manual triage decision.

> [!NOTE]
>
> A rescan replaces every result, so it also discards their triage statuses.

### Change a scan's settings

`PATCH` [`analysis_detail`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/analysis_detail/\{analysis_id}/) changes only the fields you send. A `null` ID returns `400`. An empty list is ignored. No field detaches an attachment. An empty body returns `400`.

| Field | Effect |
| - | - |
| `logo_id`, `branding_id`, `whitelist_id` | Attach a logo, a keyword set or a trusted-domain list, replacing the one attached. |
| `whitelist_domains` | Adds these domains to the attached trusted-domain list. Without one, they go to a list named after your domain, such as `acme` for `acme.com`, which is created and attached when needed. |
| `custom_domains` | Replaces the scan's custom domains. |
| `ns_record_appears_monitor`, `new_similar_domain_monitor` | Turn the two scan-wide look-alike monitors on or off. Both are off until you turn them on. See [Watch look-alike domains and read alerts](https://wiki.darknetsearch.com/api/guides/domain-monitoring-alerts.md). |

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/analysis_detail/3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63/ \
  -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"logo_id": 12, "branding_id": 4}'
```

> [!WARNING]
>
> **Monitor toggles are saved before the IDs are checked.** A `400` for an unknown `logo_id`, `branding_id` or `whitelist_id` can still leave a monitor change in place. Send toggles and attachments in separate calls.

The call returns the updated scan. Trusted domains hide matching results at once. To check the whole scan against a new logo, keyword set or custom domain list, [rescan](#stop-rescan-or-delete) it. To change the word list, send `wordlist_code` with the rescan.

### Stop, rescan or delete

| Action | Call | What happens |
| - | - | - |
| Stop | `POST` [`analysis_stop`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/POST/api/service/analysis_stop/\{analysis_id}/), no body | The scan's `status` becomes `stopped`, and the call returns the scan. Queued lookups and checks are skipped. The results found so far stay, and the scan keeps its slot. |
| Rescan | `POST` [`analysis_rescan`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/POST/api/service/analysis_rescan/\{analysis_id}/) | The scan runs again with its saved settings and attachments. Its previous results are deleted, `created_at` is reset, and `status` returns to `running`. No slot is taken. |
| Delete | `DELETE` [`analysis_delete`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/DELETE/api/service/analysis_delete/\{analysis_id}/) | The scan, its results and its look-alike monitors are removed, and its slot is freed. The call returns `204`. A deleted scan cannot be restored. |

A rescan takes an optional `wordlist_code`. Without it, the scan keeps the word list it had.

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/analysis_rescan/3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63/ \
  -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"wordlist_code": "acme-products"}'
```

The rescan returns `200` with `analysis_id`, `total_count`, `params` and the new candidates grouped by module in `variations`. Then [follow its progress](#follow-progress) as for a new scan.

A rescan that would generate more than 100,000 candidates is refused with `400`, and the scan keeps its results. The refused word list stays saved on the scan. Send a different, shorter `wordlist_code` with the next rescan.

### List scans and statistics

[`analysis_list`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_list/) returns your organization's scans, including those started in the dashboard. They come newest first.

```bash theme={"dark"}
curl -G https://client-api.leak.center/api/service/analysis_list/ \
  -H "X-API-Key: YOUR_API_KEY" \
  --data-urlencode "status=completed" \
  --data-urlencode "page_size=100"
```

* `page` starts at `1`. `page_size` defaults to `10`, and the most it returns is `100`.
* `domain` matches part of the scanned domain. `status` takes one of the four scan states.
* Each entry has `domain`, `status`, `uid`, `created_at`, `updated_at`, `params`, `total_variations` and `total_initial_done`. `uid` is the `analysis_id`.
* Raise `page` until `next` is `null`. A page past the last one returns `404`.

> [!TIP]
>
> Omit `date_sort` to list the newest first. `date_sort=desc` lists the oldest first, and `date_sort=asc` the newest first. A rescan resets `created_at`, so a rescanned domain moves to the top.

[`analysis_stats`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_stats/) sums up the last 30 days across all your scans. It takes no parameters.

* `total_alerts_count`, `total_new_similar_domain_count`, `total_new_webservers_count`, `total_spoofed_count`, `total_high_risk_domains_count` and `total_phishing_count` count look-alike alerts by kind.
* `daily_stats` has one entry per day, each with a `date` and a `data` object: candidates generated, results found, web servers found, new name server records, new similar domains, look-alike monitors created, takedown requests other than drafts, the average URL score, and that day's alerts.

### Export a scan

Both exports return a CSV file. The file name comes in the `Content-Disposition` header.

| Export | Call | Columns |
| - | - | - |
| Results | [`analysis_export`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_export/\{analysis_id}/) | Domain, Module Name, DNS Server, NS Record, A Record, MX Record, HTTP Open, HTTPS Open, Whois, Spoofing, URLScore Risk, Phishing, Screenshot, Is New, Created At, Updated At |
| Candidates | [`analysis_variations_export`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_variations_export/\{analysis_id}/) | Domain, Module Name, Created At, Updated At |

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/analysis_export/3b9e2c4a-6f1d-4e8b-9a7c-2d5f8e1b0c63/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -o acme-results.csv
```

The results export holds every result of the scan, including those your trusted domains hide. Its Module Name column holds the module code, and its Spoofing column is the brand keyword check. The candidates export lists every generated name, registered or not.

### Errors

Most API refusals use `detail`, and most scanning-service refusals use `details`. Rate-limit `429`s use `message`. The scanning service's own `429` and its `Invalid page.` `404` use `detail`. Field errors are keyed by field name. Read the first of `detail`, `details` and `message` that the body contains. [Monitor look-alike domains](https://wiki.darknetsearch.com/api/guides/domain-monitoring.md#errors-you-will-see) explains the shapes, and [Handle API errors](https://wiki.darknetsearch.com/api/guides/errors.md) lists every body.

| Status | When | Body |
| - | - | - |
| `400` | `domain` is not a registered domain asset | `{"domain": ["'shop.acme.com' is not a registered domain asset. Subdomains must be registered as their own asset."]}` |
| `400` | `domain` cannot be read as a domain name, such as a number or an invalid internationalized name | `{"domain": ["Invalid value."]}` |
| `400` | A field has the wrong type or is `null`, such as a non-numeric `logo_id` or a `wordlist_code` with spaces | `{"logo_id": ["A valid integer is required."]}` |
| `400` | The scanning service does not accept your registered asset as a domain | `{"details": "Please enter a valid domain."}` |
| `400` | The domain is one of the 100 most visited on the internet | `details` starts with `You are using a domain that belongs to the top 100 domains used in the internet.` |
| `400` | The domain already has a running scan | `details` starts with `An active scan already exists for`, plus `analysis_id`. See [Start a domain you already scan](#start-a-domain-you-already-scan). |
| `400` | 10 or more of your scans started within the last hour are still running | `details` starts with `You currently have`, then the number of your scans started or rescanned in the last hour that are still running (10 or more). Scans deleted while still running count too. |
| `400` | Another start for the same domain is still being processed | `{"details": "Another scan request for this domain is already being processed. Please wait a few seconds and try again."}` |
| `400` | `logo_id`, `branding_id` or `whitelist_id` is not in your brand library | `{"details": "Logo with this ID does not exist."}`, or the same for `Branding list` or `Whitelist`. On `PATCH`, monitor toggles sent in the same call are still saved. |
| `400` | `wordlist_code` is not one of your word lists | `{"details": "The supplied wordlist does not belong to the authenticated account."}` |
| `400` | More than 200 `custom_domains` | `{"details": "Please upload a maximum of 200 custom domains."}` |
| `400` | A rescan would generate more than 100,000 candidates | `details` starts with `Total`, then the count, then `generated domain variations exceed the 100000 limit.` |
| `400` | A `PATCH` with an empty body | `{"non_field_errors": ["At least one field must be provided."]}` |
| `400` | `status` on triage is not `open` or `reviewed`, or `domain_age` or `urlscore` is not one of its values | Keyed by the field name |
| `403` | Your plan lacks Domain Monitoring, or your license is not in force | `{"detail": "This feature is not included in your plan."}` |
| `404` | No scan with this `analysis_id`, or it was deleted | `{"details": "Analysis with this ID does not exist."}` |
| `404` | No result with this `id` in your scans | `{"details": "Analysis results with this ID does not exist."}` |
| `404` | `page` is past the last page of `analysis_list` | `{"detail": "Invalid page."}` |
| `409` | Every Monitored Assets slot is in use | See [Monitored Assets slots](https://wiki.darknetsearch.com/api/guides/domain-monitoring.md#monitored-assets-slots) |
| `429` | More than 10 start requests in an hour, or more than 180 other domain monitoring requests in 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 your API Calls allowance | `{"message": "Rate limit exceeded", ...}`. See [Rate limits](https://wiki.darknetsearch.com/api/guides/rate-limits.md). |
| `502` | The scanning service failed or sent a response the API could not read | `{"detail": "The requested service is temporarily unavailable."}` or a `message` |
| `504` | The scanning service timed out | `{"detail": "The requested service timed out."}` |

### Endpoints

| Action | Endpoint |
| - | - |
| Register a domain as an asset | [`POST /api/service/organization_assets_create/`](https://client-api.leak.center/scalar-docs/#tag/organization-settings/POST/api/service/organization_assets_create/) |
| Start a scan | [`POST /api/service/start_domain_analysis/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/POST/api/service/start_domain_analysis/) |
| Get a scan, its progress and its results | [`GET /api/service/analysis_detail/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_detail/\{analysis_id}/) |
| Change a scan's settings | [`PATCH /api/service/analysis_detail/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/analysis_detail/\{analysis_id}/) |
| Count results by age and category | [`GET /api/service/analysis_category_stats/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_category_stats/\{analysis_id}/) |
| Set a result's triage status | [`PATCH /api/service/analysis_result_update/{analysis_result_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/PATCH/api/service/analysis_result_update/\{analysis_result_id}/) |
| Stop a scan | [`POST /api/service/analysis_stop/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/POST/api/service/analysis_stop/\{analysis_id}/) |
| Rescan a domain | [`POST /api/service/analysis_rescan/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/POST/api/service/analysis_rescan/\{analysis_id}/) |
| Delete a scan and free its slot | [`DELETE /api/service/analysis_delete/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/DELETE/api/service/analysis_delete/\{analysis_id}/) |
| List scans | [`GET /api/service/analysis_list/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_list/) |
| Get 30-day statistics | [`GET /api/service/analysis_stats/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_stats/) |
| Export results as CSV | [`GET /api/service/analysis_export/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_export/\{analysis_id}/) |
| Export candidates as CSV | [`GET /api/service/analysis_variations_export/{analysis_id}/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_variations_export/\{analysis_id}/) |
| List modules, alert conditions and default word lists | [`GET /api/service/analysis_configs/`](https://client-api.leak.center/scalar-docs/#tag/spoofguard/GET/api/service/analysis_configs/) |


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