title: DomainTools Iris Detect API service_id: iris-detect auth_types: API Key, HMAC Signature source_url: https://docs.domaintools.com/api/iris/detect/ api_specification: https://docs.domaintools.com/api/iris/iris-openapi.yml ## Overview ## Product Context The Iris API suite provides three distinct products for specific security workflows: - Iris Investigate: Deep domain analysis and infrastructure mapping at human scale - Iris Enrich: High-volume domain enrichment optimized for batch processing and SIEM/SOAR integration - Iris Detect: Automated lookalike domain discovery and monitoring ## Key Capabilities - Automated discovery of lookalike domains impersonating your brands, partners, or infrastructure - Real-time monitoring with configurable watchlists - Domain triage with risk scores, DNS, and WHOIS/RDAP data - Programmatic escalation to Google Web Risk or blocking workflows - Monitor management via API for scheduling and automation ## This Documentation This reference covers the complete Iris Detect API including authentication, rate limits, the detection and monitoring guide, and working with domain screenshots. --- # Iris API Account Information The Account Information API provides a quick and easy way to get a snapshot of API product usage for an account. Usage is broken down by day and by month. ```text https://api.domaintools.com/v1/account/ ``` ## Sample Response ```json { "response": { "account": { "api_username":"domaintools-api-account", "active":true }, "products":[ { "id": "domain-profile", "per_month_limit": "100000", "per_minute_limit": "120", "absolute_limit": "1000", "usage": { "today": 5, "month": 152 }, "expiration_date": "2020-01-01" } ] } } ``` # Iris API Authentication ## Overview Most requests sent to the DomainTools API require authentication. We support two authentication schemes with different levels of security. We recommend the following practices for authentication: * Authentication with HTTPS (HTTP over SSL) instead of HTTP. * Using HMAC signed queries or Header Authentication instead of Open Key Authentication. * Using SHA-256 HMAC for the signed queries instead of MD5 or SHA-1. ## Protecting API Credentials Your account will be charged for all queries authenticated with your username and key, even if you later determine the requests were fraudulent or its use unauthorized. We recommend the following steps to protect your API credentials: * For support requests, do not send the full API key to DomainTools support. * Use a HMAC-signed approach to requests. This ensures that the user and token are not sent as part of the URL. * When required, reset the API key. * Do not place them into a public repository, such as a git repository. ## Open Key Authentication This is the easiest authentication scheme to implement, but also the most insecure. You should take precautions in the design of your application to ensure your key is not compromised. ``` https://api.domaintools.com/v1/domaintools.com?api_username=example&api_key=xxxxxx ``` | Required Parameters | Value | | --- | --- | | api_username | Your API username | | api_key | Your API key | ## API Key (Header) Authentication Authenticate your requests by including the API key in the header of each HTTP request. The API key serves as a unique identifier and is used to authenticate your requests. ### Required API Key Authentication Parameters | Required Parameters | Value | | :---- | :---- | | X-Api-Key | MY_API_KEY | ### Example Request with API Key Authentication curl -H 'X-Api-Key: MY_API_KEY' 'https://api.domaintools.com/v1/feed/nod/?after=-60 ## HMAC Signed Authentication HMAC, or hashed message authentication code, is our preferred authentication scheme. It follows the principles outlined in RFC2104 and provides a straightforward but secure method of protecting your API key. It involves passing a hash composed of your api username, the current date and time, and the request URI. This hash is then signed with your authentication key. The result is a request that expires after a brief period of time and, most importantly, does not contain your authentication key. MD5, SHA-1, and SHA-256 are supported HMAC hashing algorithms. We recommend SHA256 HMAC, as a successor of SHA1. Although NIST policy on hash functions still allows HMAC SHA-1, see Hash Functions in the NIST CSRC page. Overall, SHA-256 HMAC is also a more secure (ex, against brute force attacks) alternative to MD5 HMAC. Please check your own compliance obligations, or guidance, as to what cryptographic functions should be used. For example, see the NIST FIPS 140-2 Guidance for more information for organizations that must use FIPS 140-2 compliant algorithms. ### HMAC-Signed Authentication URI/Parameters | Required Parameters | Value | | :--- | :--- | | api_username | Your API username | | timestamp | Current timestamp, in ISO 8601 format. Timestamps should contain the timezone offset, like below: 2020-02-01T14:37:59-0800 2020-02-01T22:37:59Z 2020-02-02T10:37:59+1200 | | signature | HMAC signature of your request. SHA-256 HMAC is recommended. MD5 HMAC and SHA-1 HMAC are supported. Only sign the URL path. | ### Creating a HMAC-signed authentication request To create the signature, build a string with your API username, the timestamp in ISO 8601 format, and the URI you are requesting. That string is then signed with your API key using an HMAC function to generate the signature. The steps are below. 1. Add your api_username. The API username is the account that has been provisioned access to the relevant DomainTools API product (aka API endpoint). If this username does not have access rights, an error message will be returned. 2. Associate a timestamp. The timestamp value for the hash and timestamp parameter need to be identical. Make sure your server time is accurate and always use a fresh timestamp. 3. Add the request URI. Please see the individual API product User Guides for the endpoint’s URI format. 4. Add the host. The host is the API endpoint server. In this case, it is api.domaintools.com. 5. Use the appropriate HMAC algorithm. MD5, SHA-1, or SHA-256 for the hashing algorithm are supported. See the HMAC Algorithms section for more information. The result is a request that expires after a brief period of time and, most importantly, does not contain your authentication key in the clear. The resulting URLs will generally be similar, regardless of whichever programming language is used. ### Security Note Ensure that your current language version supports the required HMAC (and other relevant) extensions and libraries. For example, a failure in HMAC-signed URL will result in a URL with no signature value, such as below: ``` https://api.domaintools.com/v1/yourdomain.com/whois ``` # Iris Rate Limits This document explains rate limits and quota consumption for Iris Investigate, Iris Enrich, and Iris Detect in both the API and UI. ## Check your rate limits Use the following methods to determine the current rate limit associated with Iris Investigate, Iris Enrich, and Iris Detect API endpoints: 1. /account Endpoint * Querying the Account Information endpoint provides details on query limits, usage, and expiration dates for all licensed Iris endpoints. * For more information, refer to the Account Information endpoint documentation. 2. API Admin Dashboard * The API Admin can access their API dashboard to view query limits, usage, and expiration dates for all licensed endpoints. * To access the API dashboard, visit the DomainTools research page, select the account dropdown menu, and click on API Admin. ## Free test queries Multiple endpoints, including Iris Detect and Investigate, offer free test queries that don't count against your quota. Use these domains for testing and development: - domaintools.com - dnsdb.info - example.com ### Endpoints with free test queries The following endpoints support free test queries with the domains listed above: Domain Profile, Domain Reputation, Hosting History, Iris Enrich and Investigate, Reverse IP, WHOIS history, WHOIS Lookups Using these test domains allows you to verify API integration and test functionality without consuming your quota. ## Iris Investigate rate limits and quota consumption The system measures quotas at the group level and resets them each month. ### Duplicate query policies Iris Investigate treats identical queries differently depending on whether you use the UI or API: #### User Interface Identical queries within 30 days don't count against your quota. This includes: - All searches (omnisearch and advanced search) - Search hash queries - Search hash reloading - Search node revisits A query is considered identical if it has the same filters, sorting, and pagination parameters. #### API Regular queries: Identical queries within 1 hour don't count against quota. A query is considered identical if it has the same filters, sorting, and pagination parameters as a previous query made within the last hour. Search hash queries: Identical search hash queries within 10 minutes don't count against quota. A search hash query uses the search_hash parameter to retrieve previously saved search results. ### Activities that consume quota #### Pivot Engine Queries in the Iris Investigate UI The following activities consume your quota: - Executing an omnisearch (from landing or search pages) that returns results - Executing an advanced search that returns results - Sending a result to the Pivot Engine (including narrow, expand, new, and exclude functions) - Revisiting a search node more than 30 days since it was created - Loading new pages in the Pivot Engine - Sorting Pivot Engine results For information on duplicate queries that don't consume quota, see Duplicate query policies. #### Passive DNS (pDNS) Queries in the Iris Investigate UI The following activities consume your quota: - Executing a search query that returns results (from either the search field or popovers throughout the UI) - Executing/triggering the load more (infinite scroll) function in search results - Revisiting a search node more than 30 days since it was created For information on duplicate queries that don't consume quota, see Duplicate query policies. #### Queries in the Iris Investigate API The following activities consume your quota: - Executing a query - Loading additional pages of results For information on duplicate queries that don't consume quota, see Duplicate query policies. ## Iris Enrich rate limits Iris Enrich uses an independent service level with its own rate limits, separate from Iris Investigate. This independence allows Iris Enrich to be used at much greater scale and throughput than Iris Investigate. Key differences: - Independent quota: Enrich queries don't count toward your Iris Investigate quota - Separate service level: Rate limits are defined independently for Enrich - Higher throughput: Optimized for high-volume domain enrichment use cases - No pivot parameters: Unlike Investigate, Enrich is optimized for straightforward domain enrichment rather than pivoting Your Enrich service level, query caps, and rate limits are configured independently on your enterprise account. For complete details on using Iris Enrich, consult the Iris Enrich API documentation. ## Iris Detect rate limits Iris Detect has specific endpoint rate limits designed for monitoring and triage workflows. ### Domain endpoints rate limits The domains endpoints (/domains/new and /domains/watched) have a rate limit of 1 query per hour for each endpoint. Pagination: Requests using the offset parameter to retrieve additional pages of results aren't restricted by the hourly limit. If your hourly query returns more domains than the response limit, you can retrieve the complete result set using pagination without waiting. ### Development and testing During integration and testing, use the preview parameter to bypass rate limits: - Including preview=1 in requests limits responses to 2 domains - Allows up to 30 requests per minute - Enables rapid iteration during development ### Other endpoints Monitor management endpoints and domain triage actions (watchlist, ignore, escalate) have standard API rate limits. For complete details on Iris Detect API endpoints and usage, consult the Iris Detect API documentation. # Iris API Error Codes The Iris API uses standard HTTP status codes to indicate the success or failure of requests. Understanding these codes helps you handle errors gracefully and troubleshoot issues effectively. ## Status Codes | Status Code | Description | | :---------- | :---------- | | 200 | OK - The request was successful. | | 206 | Partial Content - The request was partially successful. Some data is unavailable but the request returned what was available. This typically occurs when backend services are temporarily unavailable or when data for some requested items cannot be retrieved. | | 400 | Bad Request - The request is malformed or contains invalid parameters. Check the error message for details about what needs to be corrected. | | 401 | Unauthorized - Authentication credentials are missing, invalid, or expired. Verify your API key and authentication method. | | 403 | Forbidden - The authenticated account does not have permission to access this resource or endpoint. This may indicate insufficient subscription level or access rights. | | 404 | Not Found - The requested resource does not exist. This may occur when querying for a domain that has never been registered or for data that is not available in our systems. | | 500 | Internal Server Error - An unexpected error occurred on the server. If this persists, contact DomainTools support at enterprisesupport@domaintools.com. | | 503 | Service Unavailable - The service is temporarily unavailable, typically due to maintenance or high load. Implement exponential backoff and retry the request. | ## Error Response Format Error responses follow a consistent JSON structure: ```json { "error": { "code": 400, "message": "Invalid domain name format" } } ``` ## Common Error Scenarios ### Authentication Errors (401) Cause: Missing or invalid API credentials. Solutions: - Verify your API key is correct - Check that your authentication method (header, HMAC, or basic auth) is properly configured - Ensure your API key hasn't expired ### Authorization Errors (403) Cause: Insufficient permissions or subscription level. Solutions: - Verify your account has access to the requested endpoint - Check your subscription includes the API product you're trying to use - Contact your account manager if you need additional access ### Not Found Errors (404) Cause: Requested resource doesn't exist. Common scenarios: - Querying a domain that has never been registered - Requesting historical data that predates our records - Using an invalid endpoint path ### Rate Limiting (503) Cause: Too many requests in a short time period. Solutions: - Implement exponential backoff retry logic - Check your rate limits using the Account Information endpoint - Distribute requests over time rather than in bursts - Consider upgrading your subscription for higher rate limits ## Best Practices 1. Always check status codes: Don't assume success - verify the response status code 2. Parse error messages: Error messages contain specific details about what went wrong 3. Implement retry logic: Use exponential backoff for 500 and 503 errors 4. Log errors: Keep detailed logs of errors for troubleshooting 5. Monitor rate limits: Track your API usage to avoid hitting limits ## Iris-Specific Notes ### Partial Content (206) The Iris Enrich and Investigate endpoints may return a 206 status code when: - Some backend data sources are temporarily unavailable - Data for certain requested domains cannot be retrieved - The response contains partial results rather than complete data When you receive a 206 response, the returned data is still valid and usable - it simply indicates that some information is missing. ### Detect Endpoints Iris Detect endpoints (watchlists and monitors) use a subset of the standard error codes: - 200 (OK) - 400 (Bad Request) - 401 (Unauthorized) - 403 (Forbidden) - 404 (Not Found) - 422 (Unprocessable Entity) — write endpoints only These endpoints do not return 500 or 503 errors in normal operation. ### Validation Errors (422) Iris Detect write endpoints (POST, PUT, and PATCH) return a 422 Unprocessable Entity status code when the request body is syntactically valid JSON but contains values that fail server-side validation. Unlike the standard error format, the 422 response includes per-field validation messages: ```json { "error": { "code": 422, "summary": "The given data was invalid.", "messages": { "term": ["The term field is required."], "watchlist_domain_ids": ["The watchlist domain ids field is required."] } }, "resources": { "support": "https://docs.domaintools.com" } } ``` Common validation triggers include: - Missing required fields (for example, term when creating a monitor) - Values that don't meet minimum length requirements (for example, term must be at least 3 characters) - Invalid enum values (for example, an unrecognized state value) This applies to the following endpoints: | Endpoint | Method | | :------- | :----- | | /v1/iris-detect/domains/ | PATCH | | /v1/iris-detect/escalations/ | POST | | /v1/iris-detect/monitors/ | POST | | /v1/iris-detect/monitors/ | PUT | Iris Enrich and Iris Investigate endpoints do not return 422. These endpoints return 400 for invalid parameters. # Iris Detect API guide ## Overview The Iris Detect API enables automated workflows for discovering and triaging lookalike domains that impersonate your brands, partners, or infrastructure. Retrieve newly discovered domains, query watched domains, and programmatically escalate threats for blocking or submission to Google Web Risk. For a complete overview of Iris Detect capabilities and use cases, see the Iris Detect overview. Iris Detect protects against malicious domains impersonating your brands and domains, safeguarding your organization, customers, and trademarks. You can also defend against supply chain attacks where malicious domains impersonate well-known technology vendors or partners you work with regularly. Iris Detect discovers new domains appearing globally that mimic your brands. You can quickly see key information from DNS, WHOIS/RDAP, and the DomainTools Risk Score to 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 The Detect API endpoints automate workflows and feed data from Iris Detect into other applications. Many actions performed via the Detect UI can be programmatically scheduled for convenience. ### Functionality supported via APIs * Read: Retrieve data about discovered domains, monitors, and escalations * Write: Make changes such as adding a domain to the watchlist or escalating a domain for further action * Monitor management: Create, update, and delete monitors programmatically ### Not supported by API * Event-based updates: There is no way to "subscribe" to changes. All updates must be retrieved by "pull" action. However, you can schedule email alerts for regular updates within the UI. ## 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 escalate domains. By default, users have read-only access to the application. To use the Detect APIs, you need your username and an API key. ## Authentication Consult the Iris API authentication options for details on the available authentication methods. ## Authorization and permissions API accounts require specific permissions to perform domain triage actions. These permissions must be configured by your account administrator. ### Permission types Depending on your account configuration, you may have different levels of access: * Read-only permissions: The account can only retrieve discovered domains but cannot perform triage actions. Accounts with read-only permissions don't have access to the add/remove to watchlist endpoint or escalation endpoints. * Read + write permissions: The account has full access to perform domain triage actions including: - Adding domains to the watchlist - Ignoring domains - Escalating domains (for internal blocking or to Google Safe Browsing) ### Required permissions for API actions To perform domain triage actions via the API, your API account must have the following permissions configured: * Add to watchlist: Required to add domains to your watchlist for ongoing monitoring * Ignore: Required to mark domains as false positives and remove them from active monitoring * Escalate: Required to escalate domains for internal blocking or to Google Safe Browsing * Manage monitors: Required to create, update, or delete monitors via the API If you need these permissions enabled for your API account, contact your account administrator. ## API rate 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 and domains/watched calls. * Pagination requests: 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 the offset 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 preview parameter in requests limits the responses to just 2 domains but allows for up to 30 requests per minute. This enables rapid iteration during development and testing. (Use the preview parameter for development and testing only. Don't use it for sustained production queries. Sustained usage violates our Terms of Service and can result in service suspension.) For complete information about Iris API rate limits across all products, consult the Iris API rate limits documentation. ## 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. 1. In the API Product Information tab, go to the section called API Username to obtain your username. 2. In the same tab, you can find your API Key. 3. 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 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. 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 retrieves 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 shows the number of domains associated with the various categories such as New, Changed, etc. for each monitor. You can sort and order the results with options such as term, creation date, created by, and others. #### Endpoint URL ``` https://api.domaintools.com/v1/iris-detect/monitors ``` #### 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=&api_key= ``` ### Create monitor Create a new monitor to track lookalike domains for a specific term. The monitor begins discovering matching domains immediately after creation. Requires the "manage monitors" permission. #### Endpoint URL ``` https://api.domaintools.com/v1/iris-detect/monitors/ ``` #### Method POST #### Required parameters (JSON body) | Name | Type | Description | | --- | --- | --- | | term | string | The keyword to monitor for domain variations. | #### Optional parameters (JSON body) | Name | Type | Default | Description | | --- | --- | --- | --- | | match_substring_variations | boolean | false | When true, includes domains where variations of the term appear as substrings within matched domains. See how domain matching works. | | nameserver_exclusions | string[] | [] | Nameserver patterns to exclude. Wildcards (`) are accepted (for example, .domaintools.com). A domain is excluded only when all of its nameservers match an exclusion pattern. | | text_exclusions | string[] | [] | Text strings to exclude from results. Domains containing any of these strings are excluded. | #### Example usage ##### Create a monitor with exclusions ``` POST https://api.domaintools.com/v1/iris-detect/monitors/?api_username=&api_key= ``` Body: ```json { "term": "domaintools", "match_substring_variations": true, "text_exclusions": ["selection", "redomaintools"], "nameserver_exclusions": ["*.domaintools.com"] } ``` #### Response The response includes a status field and the created monitor object: ```json { "status": "created", "monitor": { "term": "domaintools", "match_substring_variations": true, "nameserver_exclusions": ["*.domaintools.com"], "text_exclusions": ["selection", "redomaintools"], "id": "oab3nQ7m8B", "created_date": "2026-03-02T18:33:04.245472Z", "updated_date": "2026-03-02T18:33:04.245472Z", "state": "active", "status": "pending", "created_by": "" } } ``` The monitor status is pending immediately after creation and changes to completed once initial domain discovery finishes. ### Update monitor Update the configuration of an existing monitor. You can modify match settings and exclusions without recreating the monitor. Requires the "manage monitors" permission. Note: A recently created monitor may not be immediately available for updates. Wait until the monitor's status changes from pending to completed before sending update requests. #### Endpoint URL ``` https://api.domaintools.com/v1/iris-detect/monitors/ ``` #### Method PUT #### Required query parameters | Name | Type | Description | | --- | --- | --- | | monitor_id | string | The ID of the monitor to update. Retrieve monitor IDs from the monitor list endpoint. | #### Optional parameters (JSON body) | Name | Type | Description | | --- | --- | --- | | match_substring_variations | boolean | Enable or disable substring variation matching. | | nameserver_exclusions | string[] | Replace the current nameserver exclusion list. Wildcards (*) are accepted. | | text_exclusions | string[] | Replace the current text exclusion list. | Include only the fields you want to change. Omitted fields retain their current values. #### Example usage ##### Enable substring matching on an existing monitor ``` PUT https://api.domaintools.com/v1/iris-detect/monitors/?monitor_id=JKwjv5Xp8x&api_username=&api_key= ``` Body: ```json { "match_substring_variations": true } ``` ##### Update text exclusions ``` PUT https://api.domaintools.com/v1/iris-detect/monitors/?monitor_id=JKwjv5Xp8x&api_username=&api_key= ``` Body: ```json { "text_exclusions": ["selection", "pineapple"] } ``` ### Delete monitor Permanently delete a monitor and stop tracking its associated domains. Requires the "manage monitors" permission. #### Endpoint URL ``` https://api.domaintools.com/v1/iris-detect/monitors/ ``` #### Method DELETE #### Required query parameters | Name | Type | Description | | --- | --- | --- | | monitor_id | string | The ID of the monitor to delete. Retrieve monitor IDs from the monitor list endpoint. | #### Request body None. #### Example usage ##### Delete a monitor ``` DELETE https://api.domaintools.com/v1/iris-detect/monitors/?monitor_id=JKwjv5Xp8x&api_username=&api_key= ``` #### Response The response confirms the deletion and returns the monitor ID: ```json { "status": "deleted", "monitor": { "id": "JKwjv5Xp8x" } } ``` ### 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 provides 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 ``` GET ``` #### 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[]= for each TLD. Do not combine TLDs in a single tlds[] parameter. | | 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. | | screenshots | flag | 1 | | Set to 1 to include screenshot data in the response. See working with screenshots for 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 2 but not be limited by hourly restrictions. For development and testing only; sustained usage violates Terms of Service. | #### 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=&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_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=&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=&api_key= ``` ### Ignored domains The Ignored Domains endpoint enables users to retrieve details about domains that have been marked as ignored (false positives) across their monitors. When a domain is marked as ignored, it's removed from active monitoring and no longer generates alerts. This endpoint allows you to review ignored domains and, if needed, move them back to your watchlist. Like the other domain endpoints, you can retrieve ignored domains for a specific monitor or across all monitors. Various optional parameters are available to filter and search the results. #### Endpoint URL ``` https://api.domaintools.com/v1/iris-detect/domains/ignored/ ``` #### Method ``` GET ``` #### 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. | | tlds | string[] | Use tlds[]= for each TLD. Do not combine TLDs in a single tlds[] parameter. | | 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 to control the timeframe for when a domain was discovered. Inclusive. | | changed_since | datetime OR integer | ISO-8601 date/time format for absolute time OR a negative integer for the (relative) number of seconds ago. | | Filters domains based on when they were last changed. | | escalated_since | datetime OR integer | ISO-8601 date/time format for absolute time OR a negative integer for the (relative) number of seconds ago. | | Filters domains based on when they were 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 2 but not be limited by hourly restrictions. For development and testing only; sustained usage violates Terms of Service. | #### Example usage ##### Retrieve all ignored domains ``` GET https://api.domaintools.com/v1/iris-detect/domains/ignored/?api_username=&api_key= ``` ##### Retrieve ignored domains for a specific monitor ``` GET https://api.domaintools.com/v1/iris-detect/domains/ignored/?monitor_id=JKwjv5Xp8x&api_username=&api_key= ``` ##### Retrieve ignored domains discovered within a specific timeframe ``` GET https://api.domaintools.com/v1/iris-detect/domains/ignored/?discovered_since=2023-01-01&discovered_before=2024-01-01&api_username=&api_key= ``` ##### Search for specific ignored domains ``` GET https://api.domaintools.com/v1/iris-detect/domains/ignored/?search=example&api_username=&api_key= ``` ### Add and 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: ``` https://api.domaintools.com/v1/iris-detect/domains/?api_username=&api_key= ``` Body: ``` { "watchlist_domain_ids": [""], "state": "watched" } ``` ##### Remove domain from watchlist URL ``` https://api.domaintools.com/v1/iris-detect/domains/?api_username=&api_key= ``` Body: ``` { "watchlist_domain_ids": [""], "state": "ignored" } ``` ### 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: ``` https://api.domaintools.com/v1/iris-detect/escalations/?api_username=&api_key= ``` Body: ``` { "watchlist_domain_ids": [""], "escalation_type": "google_safe" } ``` ##### Escalate for internal blocking URL: ``` https://api.domaintools.com/v1/iris-detect/escalations/?api_username=&api_key= ``` Body: ``` { "watchlist_domain_ids": [""], "escalation_type": "blocked" } ``` ## Working with screenshots You can retrieve domain screenshots through the Iris Detect API by adding the screenshots=1 parameter to your domain requests. For detailed information about retrieving, resizing, and interpreting screenshot data, see working with screenshots in Iris APIs. ## Appendix: API response examples ### Monitor 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=&api_key= ``` #### Response example This is a sample of the response, including counts for each monitor: ```json { "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": "" } ] } ``` ### 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=&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 initial proximity or phishing scores within a few minutes and the score is designated as provisional. Full risk scoring (across all 4 algorithms including malware and spam) is typically available within 15-20 minutes of discovery. Risk scores are also updated when significant changes are detected to a domain's DNS records or other attributes. All active domains continue to be scored daily. ```json { "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": "" } ], "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: ``` PATCH https://api.domaintools.com/v1/iris-detect/domains/?api_username=&api_key= ``` Request Body: ``` { "watchlist_domain_ids": ["AaLMA1oOE0"], "state": "watched" } ``` #### Response example ```json { "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": "", "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=&api_key= ``` Request body: ``` { "watchlist_domain_ids": ["AaLMA1gOE0"], "escalation_type": "blocked" } ``` #### Response example ```json { "escalations": [ { "watchlist_domain_id": "AaLMA1gOE0", "escalation_type": "blocked", "id": "BWdgkK8g6p", "created_date": "2022-01-20T23:25:48.990908+00:00", "updated_date": "2022-01-20T23:25:48.990908+00:00", "created_by": "" } ] } ``` # Working with screenshots in Iris APIs Retrieve the most recent screenshot for a given domain with Iris APIs in a two-step process: 1. Retrieve the screenshot image URL 2. Retrieve and optionally resize the image file Also consult the section on interpreting screenshot metadata. ## Retrieve the screenshot URL {#get-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 ```json "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" } ``` ## Retrieve and optionally resize the screenshot image via its URL {#get-image} 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 {#interpretation} 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: ```json "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 and last_attempt are equal. Response example: ```json "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 to timestamp, because that was the last time a screenshot was successfully observed - last_attempt is more recent than last_seen, but the attempt failed Response example: ```json "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 date - last_seen is later than timestamp, indicating the image was revalidated as a duplicate on a later date - last_attempt reflects a more recent failed attempt to recapture the screenshot Example response: ```json "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" } ```