Iris Detect API Reference¶
Introduction¶
Iris Detect protects against malicious domains impersonating your brands and domains so you can safeguard your organization, your customers, and your trademarks. You can also defend against supply chain attacks where malicious domains impersonate either well-known technology vendors or even partners you work with on a regular basis. Iris Detect does this by discovering new domains appearing globally that mimic your brands. You can quickly see key information from DNS, WHOIS/RDAP and the DomainTools Risk Score to easily assess the level of threat. Iris Detect also monitors domains over time so you can see how they evolve, and take action as needed.
About Iris Detect APIs¶
A number of the actions performed via the Detect UI can be programmatically scheduled for convenience. The Detect API endpoints automate workflows further and feed data from Iris Detect into other applications.
Functionality Supported via APIs:
- Read: Retrieve data
- Write: Make changes such as adding a domain to the watchlist or escalating a domain for further action.
Not supported by API in Version 1.0
- Monitor Creation: All monitors need to be created via the Iris Detect UI. Due to the nature of this task and how iterative it can become, it will not be supported via programmatic access at this time.
- Screenshots: Screenshot retrieval is not supported via API at this time.
- Event-Based Updates: There is no way to “subscribe” to changes, all updates need to be retrieved by “pull” action. However, scheduling email alerts for regular updates within the UI is possible.
Getting Started¶
Iris Detect requires an Enterprise account login on DomainTools, and your account must include Iris Detect access. Additionally, user permissions control whether users can manage monitors, triage domains, or escalated domains. By default, users have read-only access to the application. For using the Detect APIs you will also need your username as well as an API Key.
API Limits¶
Endpoints with Special Rate Limits¶
- Domains: The Domains endpoints can be queried with a frequency of up to once per hour for each the
domains/new
anddomains/watched
calls. - Pagination requests to get full domain lists are not restricted. For example, if the hourly call for new domains returns more than the
limit
of domains returned in a single response, the additional domains can be queried using theoffset
variable to complete the results without being impacted by the hourly restriction.
Bypassing Rate Limits During Integration Work¶
During integration of the domain API endpoints, including the the preview
parameter in requests will limit the responses to just 10 domains but allows for up to 30 requests per minute. This enables rapid iterative during development and testing.
Authentication¶
Please consult our authentication options.
Authorization¶
Depending on your account type, you may have the ability to only retrieve the latest discovered domains and or add said domains to the watchlist for ongoing monitoring and analysis.
- Read-Only Permissions: The account will not have permissions to the add/remove to watchlist endpoint.
- Read + Write Permissions: The account will have all existing permissions.
Finding and Resetting the API Key¶
To find or reset the DomainTools API key via https://research.domaintools.com/:
Login to the DomainTools API Dashboard. Only the API owner account can reset the API key. There are two places to access this:
- Select the Account menu and select the API Admin menu item to access the API Dashboard.
- In the My Account section, select the View API Dashboard link that is located in the Account Summary tab.
- In the API Product Information tab, go to the section called API Username to obtain your username.
- In the same tab, you can find your API Key.
- To reset your API key:
- Select the Reset API Key.
- Creating a new key will cause the existing key to be discarded immediately. This action cannot be undone.
- Any requests that are made with the old key will no longer validate for this user.
API Endpoints¶
Monitor List¶
As the name specifies, this endpoint allows users to retrieve the monitors and their respective IDs for your account. The monitor IDs can then be used to retrieve newly discovered or recently changed domains for individual monitors using the monitor_id
variable.
On the other hand, you can also request new or changed domains across all monitors in a single request by not specifying the monitor_id
variable. Since the endpoint is limited to 1 query request per hour, making a request for all monitors will retrieve results for all monitors every hour. The monitor endpoint can still be used to help map domains to their monitor if that is important for the integration.
The include_counts
variable will show the number of domains associated with the various categories such as New, Changed, etc. for each monitor.
It’s possible to sort and order the results with options such as term, creation date, created by, and others. The required and optional parameters are outlined below.
The /ignored
endpoint allows you to view domains you have ignored.
Endpoint URL¶
Method¶
GET
Conditionally Required Parameters¶
Name | Type | Valid values | Default values | Notes |
---|---|---|---|---|
datetime_counts_since |
datetime OR integer | ISO-8601 date/time format for absolute time OR a negative integer for the (relative) number of seconds ago. | Conditionally required if the include_counts parameter is included. |
Optional Parameters¶
Name | Type | Valid values | Default values | Notes |
---|---|---|---|---|
include_counts |
bool | false | Includes counts for each monitor for new, watched, changed and escalated domains | |
sort |
string[] | term, created_date, domain_counts_changed, domain_counts_discovered | term | Provides options for sorting the monitor list. |
order |
string | asc, desc | desc | Toggles ordering for selected sort option. |
offset |
int | 0-100000 | 0 | For paginating requests beyond the limit. |
limit |
int | 500 | Restricted to maximum 100 if include_counts=true |
Example Usage¶
Retrieve All Monitors with Counts¶
GET https://api.domaintools.com/v1/iris-detect/monitors/?datetime_counts_since=2022-01-14%2016:27:31&include_counts=true &api_username=<username>&api_key=<API key>
Domains¶
The Domains endpoint enables users to retrieve details associated with domains for a specific monitor or all monitors. The endpoint can be used to view:
- Newly discovered domains
- Recently changed domains (with changes to key DNS and RDAP/WHOIS data tracked by the application)
- Domains that have been recently escalated in the application, with the escalations being for internal blocking or for sending the domains to Google’s Web Risk service.
- Escalations can be triggered either directly in the application UX or via API (covered in the Escalation section below).
A number of optional parameters are made available to filter the results as needed.
The /new
endpoint can provide newly discovered domains for monitors created in Iris Detect.
The /watched
endpoint will provide recently changed domains for the domains from a monitor’s list of watched domains. (Domains can be selected for watching from either the Iris Detect UX or via API, discussed below.)
The /watched
endpoint can also be used to query for domains that have been escalated for blocking or to Google Safe browsing. (Domains can be escalated either from the Iris Detect UX or via API, discussed below).
Endpoint URL¶
https://api.domaintools.com/v1/iris-detect/domains/new/
https://api.domaintools.com/v1/iris-detect/domains/watched/
Method¶
Required Parameters¶
None
Optional Parameters¶
Name | Type | Valid values | Default values | Notes |
---|---|---|---|---|
monitor_id |
string | Monitor ID from the monitors response – only used when requesting domains for specific monitors. | ||
escalation_types |
string[] | blocked, google_safe | Filters on specific escalation types | |
tlds |
string[] | Use tlds[]= |
Filters on one or multiple TLDs | |
risk_score_ranges |
string[] | 0-0, 1-39, 40-69, 70-99, 100-100 | Filters on domains with a risk score in different ranges. | |
mx_exists |
boolean | Whether domain currently has an MX record in DNS. | ||
domain_state |
string | active, inactive | ||
discovered_before |
datetime OR integer | ISO-8601 date/time format for absolute time OR a negative integer for the (relative) number of seconds ago. | Can be used with discovered_since to define a complete date/time window. Exclusive. |
|
discovered_since |
datetime OR integer | ISO-8601 date/time format for absolute time OR a negative integer for the (relative) number of seconds ago. | Can be used with discovered_before . Relevant for the /new endpoint to control the timeframe for when a new domain was discovered. Inclusive. |
|
changed_before |
datetime OR integer | ISO-8601 date/time format for absolute time OR a negative integer for the (relative) number of seconds ago. | Most relevant for the /watched endpoint to control the timeframe for changes to DNS or WHOIS/RDAP fields for watched domains. |
|
changed_since |
datetime OR integer | ISO-8601 date/time format for absolute time OR a negative integer for the (relative) number of seconds ago. | Most relevant for the /watched endpoint to control the timeframe for changes to DNS or WHOIS/RDAP fields for watched domains. |
|
escalated_since |
datetime OR integer | ISO-8601 date/time format for absolute time OR a negative integer for the (relative) number of seconds ago. | Most relevant for the /watched endpoint to control the timeframe for when a domain was most recently escalated. |
|
search |
string | A “contains” search for domain name. | ||
sort |
string[] | discovered_date, changed_date, risk_score | Sort order of domain list response. | |
order |
string | asc, desc | Ordering options for sorting | |
include_domain_data |
boolean | Includes DNS and RDAP/WHOIS details. | ||
offset |
int | 0-100000 | 0 | For paginating requests beyond the response limit. No other parameter values can change when paginating. |
limit |
int | 0-100 or 0-50 if include-domain-data=true | 0 | Limits result size. |
preview |
boolean | Use during API implementation and testing.Including with value = 1 will limit results to 10 but not be limited by hourly restrictions. |
Example Usage¶
Note that date/time format follows ISO-8601. Not including a timezone indicator will be assumed to be in Pacific Time Zone.
Retrieve newly discovered domains since a specific date/time for Pacific Standard Time with millisecond precision¶
GET https://api.domaintools.com/v1/iris-detect/domains/new/?discovered_since=2022-01-12%2000:00.000000%20-08:00&api_username=<username>&api_key=<API key>
Retrieve all watched domains that changed within a given set of dates¶
GET https://api.domaintools.com/v1/iris-detect/domains/watched/?api_key=<api_key>&api_username=<username>&discovered_since=2023-01-01&discovered_before=2024-01-01
Retrieve domain that have been escalated for internal blocking since a specific date/time for Pacific Standard Time¶
GET https://api.domaintools.com/v1/iris-detect/domains/watched/?escalated_since=2022-01-11%2016:00:00%20-08:00&api_username=<username>&api_key=<API key>&escalation_types[]=blocked
Retrieve domains when results exceed response limit of 100 results using offset parameter.¶
- Example shows subsequent call for second group of 100 domains
GET https://api.domaintools.com/v1/iris-detect/domains/new/?offset=100&api_username=<username>&api_key=<API key>
Add & Remove from Watchlist¶
Analyzing and triaging newly discovered domains is an activity that should be done regularly, so New domains only show recently discovered domains. Triage options include:
- Add to Watchlist: Adding a domain to the Watchlist removes it from New and allows tracking of when domains most recently changed in DNS or WHOIS/RDAP. Watched domains will have screenshots captured daily so you see how the webpage evolves over time.
- Ignore: If a domain is obviously a false positive, Ignoring the domain removes it from New and places it under Ignored. The decision can always be reversed and the domain can be moved from Ignored to Watched instead.
Endpoint URL¶
https://api.domaintools.com/v1/iris-detect/domains/
Method¶
PATCH
Required Parameters¶
Name | Type | Valid values | Default value | Notes |
---|---|---|---|---|
watchlist_domain_ids | string[] | ID(s) of domains being triaged. | ||
state | string | watched, ignored | Add domains to Watchlist or ignore and mute alerts for those domains. |
Optional Parameters¶
None
Example Usage¶
Add Domain to Watchlist¶
URL:
Body:
Remove Domain from Watchlist¶
URL
Body:
Escalate¶
Two escalation activities are supported for the API as shown below.
Escalating a New domain will also add it to be Watched for changes.
- Domains can be sent to Google Web Risk. If Google agrees the domain is malicious, it will be blocked in Chrome browsers globally. This list is also picked up by Apple for their Safari browser and Firefox.
- Domains can be marked for Blocking if they are to be blocked in internal network defense infrastructure. Loading a domain into a company’s firewalls and other systems needs to take place via API query combined with a system action on the customer end.
- Limits for escalation request API calls
- Blocked domains: A maximum of 100 domains per request.
- Google Web Risk: A maximum of 10 domains per request.
- There is a limit of 30 requests per minute (each request can include multiple domains per above).
Endpoint URL¶
https://api.domaintools.com/v1/iris-detect/escalations/
Method¶
POST
Required Parameters¶
Name | Type | Valid values | Default value | Notes |
---|---|---|---|---|
watchlist_domain_ids | string[] | ID(s) of domains to be escalated | ||
escalation_type | string | blocked, google_safe |
Optional Parameters¶
None
Example Usage¶
Escalate to Google Safe Browsing¶
URL:
Body:
Escalate for Internal Blocking¶
URL:
Body:
Retrieve Screenshots in Iris APIs¶
Retrieve the most recent screenshot for a given domain with Iris APIs in a two-step process:
Also consult the section on interpreting screenshot metadata, below.
1. Retrieve the Screenshot URL¶
Append queries with screenshots=1
to receive a screenshot
JSON object in the response.
For example, the following Iris API queries (with header authentication) include screenshot requests.
Example Queries for Screenshot URL Retrieval¶
- Iris Detect:
https://api.domaintools.com/v1/iris-detect/domains/watched/?screenshots=1
- Iris Enrich:
https://api.domaintools.com/v1/iris-enrich/?domain=example.com&screenshots=1
- Iris Investigate:
https://api.domaintools.com/v1/iris-investigate/?domain=example.com&screenshots=1
Query Parameters for Screenshot URL Retrieval¶
Query Parameter | Required | Type | Valid Values | Description | Example |
---|---|---|---|---|---|
screenshots |
yes | flag (1) | 1 |
Triggers screenshot object in response. | screenshots=1 |
Response Fields for Screenshot URL Retrieval¶
Output field | Type | Valid Values | Description | Example |
---|---|---|---|---|
ip_address |
string | null | IP address | The IP address from which the screenshot was taken. | 212.129.31.169 |
last_attempt |
string | ISO 8601 date-time format | The date and time the screenshot was last attempted. | 2025-02-17T15:34:55Z |
last_seen |
string | ISO 8601 date-time format | The date and time the screenshot was last observed | 2025-02-17T15:34:55Z |
screenshot |
object | JSON object | Details about the screenshot. | |
src |
str | URL | Link to the screenshot. | https://screenshots.ne.domaintools.com/screenshot_image?s3v=1&rurl=http%3A%2F%2Fespn.com&ts=2024-03-28T21%3A48%3A37Z&token=dec12499e06b61d17175c683387307c9b751c71fbbbd797b8e094c2c288f2b31 |
timestamp |
string | ISO 8601 date-time format | The date and time the provided screenshot (in fullsize field) was obtained. |
2024-08-05T16:17:45Z |
Response Example for Screenshot URL Retrieval¶
"screenshot": {
"timestamp": "2025-03-07T19:53:44Z",
"src": "https://screenshots.ar.domaintools.com/screenshot_image?s3v=1&rurl=http%3A%2F%2Fdomaintools.com&ts=2025-03-07T19%3A53%3A44Z&token=2d6269e40f4bc48908b17d218e5647fc90c0034618e39ec20806910d3909785c",
"ip_address": "141.193.213.21",
"last_attempt": "2025-04-07T18:00:01Z",
"last_seen": "2025-04-07T18:00:01Z"
}
2. Retrieve and Optionally Resize the Screenshot Image via its URL¶
Use the src
URL in the returned screenshot
object to download the screenshot image. The URL already contains the required parameters domain
, ts
, rurl
, and token
. Optionally add resize_width
and crop_height
to resize the image.
Query Parameters for Screenshot Image File¶
Query Parameter | Required | Type | Valid Values | Description | Example |
---|---|---|---|---|---|
resize_width |
no | integer | Width in pixels | If the value is less than the width of the image, the image will be shrunk horizontally to the given resize_width, preserving the aspect ratio. | resize_width=500 |
crop_height |
no | integer | Height in pixels | If the value is less than the height of the image, the image will be cropped vertically to the given crop_height, removing pixels from the bottom of the image. | crop_height=500 |
Example Query for Screenshot Image File¶
api.domaintools.com/screenshot_image?domain=domaintools.com&ts=2025-04-30T14:32:10Z&resize_width=500&crop_height=500&rurl=https://www.domaintools.com/
Interpreting Screenshot Metadata¶
Use the last_attempt
, last_seen
, and timestamp
to interpret the screenshot.
To confirm that the most recent screenshot was gathered during the current domain lifecycle—and isn't from an older, historic screenshot—compare the screenshot's timestamp
with the domain's first_seen
value in the API response. If the timestamp
is later than first_seen
, the screenshot was taken during the current domain lifecycle.
Initial capture¶
The screenshot was successfully captured during the first and only attempt. Since there have been no subsequent checks, all timestamp fields are identical.
Relationships: timestamp
= last_seen
= last_attempt
Response example:
"screenshot": {
"timestamp": "2025-05-12T14:38:19Z",
"src": "https://screenshots.ar.domaintools.com/screenshot_image?s3v=1&rurl=http%3A%2F%2Fxumi.fr&ts=2025-05-12T14%3A38%3A19Z&token=5fbd3aa604682d26d9f1f69810a87bfd75ea25e56eadb3553cefcff2ba804f28",
"ip_address": "76.76.21.21",
"last_attempt": "2025-05-12T14:38:19Z",
"last_seen": "2025-05-12T14:38:19Z"
}
Gather attempt was duplicate of initial screenshot¶
DomainTools re-checked a domain after previously taking an initial screenshot. The result was identical to the existing image and no new screenshot was generated.
Relationships: timestamp
< last_seen
= last_attempt
timestamp
remains unchanged, preserving the original capture time.last_attempt
is updated to reflect the most recent screenshot check.last_seen
is updated to indicate the most recent time the image was confirmed valid.- Because no new image was needed,
last_seen
andlast_attempt
are equal.
Response example:
"screenshot": {
"timestamp": "2025-05-12T10:10:49Z",
"src": "https://screenshots.ar.domaintools.com/screenshot_image?s3v=1&rurl=http%3A%2F%2Fdomaintools.co.in&ts=2025-05-12T10%3A10%3A49Z&token=28d255010a09d1cc8a3326e1c1406971910293f09ddac0159eb35391f705be57",
"ip_address": "104.219.250.192",
"last_attempt": "2025-05-13T17:16:34Z",
"last_seen": "2025-05-13T17:16:34Z"
}
Recapture failed after previous successful capture¶
DomainTools successfully captured a screenshot on a previous attempt. The next attempt to capture the screenshot failed — the system was unable to retrieve a new image and could not confirm whether the content had changed.
Relationships: timestamp
= last_seen
, and last_seen
< last_attempt
timestamp
reflects the time the screenshot was originally captured.last_seen
is equal totimestamp
, because that was the last time a screenshot was successfully observedlast_attempt
is more recent thanlast_seen
, but the attempt failed
Response example:
"screenshot": {
"timestamp": "2023-12-19T22:17:10Z",
"src": "https://screenshots.ar.domaintools.com/screenshot_image?s3v=1&rurl=http%3A%2F%2Ffixhelpdesk.com&ts=2023-12-19T22%3A17%3A10Z&token=8cd6edb822594a0aa485e72f5cbb5414a73b657f7438b770844f46fe886c4ea9",
"ip_address": "91.195.240.19",
"last_attempt": "2025-05-13T10:25:04Z",
"last_seen": "2023-12-19T22:17:10Z"
}
Duplicate capture followed by failed attempt¶
A screenshot was captured, and subsequently re-captured as a duplicate. A subsequent attempt to refresh the (duplicate) screenshot failed.
Relationships: timestamp
< last_seen
, and last_seen
< last_attempt
timestamp
reflects the original screenshot datelast_seen
is later thantimestamp
, indicating the image was revalidated as a duplicate on a later datelast_attempt
reflects a more recent failed attempt to recapture the screenshot
Example response:
"screenshot": {
"timestamp": "2022-07-02T10:03:43Z",
"src": "https://screenshots.ar.domaintools.com/screenshot_image?s3v=1&rurl=http%3A%2F%2Fdomaintools.ca&ts=2022-07-02T10%3A03%3A43Z&token=6fa06c07ff1b7206ae8f38aadaf4e11b8cf538b7625944e2813a72ebec2c6648",
"ip_address": "158.85.87.76",
"last_attempt": "2025-05-13T10:12:04Z",
"last_seen": "2024-05-22T10:11:09Z"
}
Appendix 1: Examples of API Responses¶
Monitors List Example¶
This is a sample of the response from a query to the Monitor List endpoint, preceded by the request:
Request example¶
GET https://api.domaintools.com/v1/iris-detect/monitors/?datetime_counts_since=2022-01-20%2011:03:21&include_counts=true&api_username=<username>&api_key=<API key>
Response example¶
This is a sample of the response, including counts for each monitor:
{
"total_count": 16,
"offset": 0,
"limit": 500,
"monitors": [
{
"term": "domaintools",
"match_substring_variations": true,
"nameserver_exclusions": [],
"text_exclusions": [],
"id": "JKwjv5Xp8x",
"created_date": "2022-01-15T00:32:04.418134+00:00",
"updated_date": "2022-01-15T00:32:04.418134+00:00",
"state": "active",
"status": "completed",
"domain_counts": {
"new": 2,
"watched": 5,
"escalated": 1,
"changed": 2
},
"created_by": "<username>"
}
]
}
Domain List Example¶
The following example is for querying domains/new endpoint, the results would be the same for the domains/changed endpoint for querying either changed domains or domains that have been escalated since a given date/time.
Request Example¶
The request includes the boolean variable to include domain data for key fields for DNS and WHOIS/RDAP.
GET https://api.domaintools.com/v1/iris-detect/domains/new/?discovered_since=2022-01-20%20%2009:40:12.000000%20-08:00&api_username=<username>&api_key=<API key>&include_domain_data=1
Response Example¶
This is an example of the response, including details for DNS and WHOIS/RDAP data. Note the “risk_score_status": "provisional"
field used to indicate a partially example of the response, including details for DNS and WHOIS/RDAP data. The risk score status indicates whether the scoring is provisional or full. Newly discovered domains will have only initial proximity or phishing scores and the score is designated as provisional. After 24-36 hours, a full risk score is calculated and adds malware and spam scoring values.
{
"watchlist_domains": [
{
"state": "new",
"domain": "bestanbanks.in",
"status": "active",
"discovered_date": "2022-01-20T20:26:14.378000+00:00",
"changed_date": "2022-01-20T20:27:58.000000+00:00",
"risk_score": 67,
"risk_score_status": "provisional",
"risk_score_components": {
"proximity": 21,
"threat_profile": {
"phishing": 67
}
},
"mx_exists": true,
"tld": "in",
"id": "8avjyB1Xaj",
"escalations": [
{
"escalation_type": "blocked",
"id": "p6db6jQbVJ",
"created": "2022-01-07T16:44:40.491903+00:00",
"created_by": "<username>"
}
],
"monitor_ids": [
"Y41pGXBjEq"
],
"name_server": [
{
"host": "dimitris.ns.cloudflare.com"
},
{
"host": "zainab.ns.cloudflare.com"
}
],
"registrant_contact_email": [
"please contact the registrar listed above"
],
"registrar": "GoDaddy.com, LLC",
"create_date": 20220120,
"ip": [
{
"country_code": "US",
"ip": "172.67.192.30",
"isp": "CloudFlare Inc."
},
{
"country_code": "US",
"ip": "104.21.81.241",
"isp": "CloudFlare Inc."
}
],
"mx": [
{
"host": "mx1.hostinger.in"
},
{
"host": "mx2.hostinger.in"
}
]
}
],
"total_count": 1,
"count": 1,
"offset": 0,
"limit": 100
}
Add Domain To Be Watched Example¶
This request is for adding a domain to the account’s Watchlist. A similar request is used to ignore domains, using the "state" : "ignored"
instead of "state" : "watched"
.
Request Example¶
Request URL:
Request Body:
Response Example¶
{
"watchlist_domains": [
{
"state": "watched",
"domain": "facebook-09835.pl",
"discovered_date": "2022-01-20T18:35:29.801000+00:00",
"changed_date": "2022-01-20T18:57:34.000000+00:00",
"id": "AaLMA1oOE0",
"assigned_by": "<username>",
"assigned_date": "2022-01-20T22:27:39.000000+00:00"
}
]
}
Escalate a Domain for Blocking Example¶
This request is for escalate a domain for internal blocking. A similar request is used to escalate domains to Google Safe Browsing using the "escalation_type" : "google_safe"
instead of "escalation_type" : "blocked"
.
Request Example¶
URL requested:
POST https://api.domaintools.com/v1/iris-detect/escalations/?api_username=<username>&api_key=<API key>
Request body: