From 1832eaa40d305ef4722f4946439dc36d69d7a220 Mon Sep 17 00:00:00 2001 From: JD Babac Date: Fri, 5 Jun 2026 01:00:41 +0800 Subject: [PATCH 1/3] IDEV-2478: Add domain_history in python wrapper. --- domaintools/api.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/domaintools/api.py b/domaintools/api.py index f62513e..7f04598 100644 --- a/domaintools/api.py +++ b/domaintools/api.py @@ -275,6 +275,57 @@ def domain_profile(self, query, **kwargs): """Returns a profile for the specified domain name""" return self._results("domain-profile", "/v1/{0}".format(query)) + def domain_history( + self, + query, + include_fields=None, + exclude_fields=None, + page_size=None, + offset=None, + next=None, + parsed_whois=None, + parsed_domain_rdap=None, + **kwargs, + ): + """Returns the history of changes for a given domain name. + + Results are returned in reverse chronological order. Each change event includes + a timestamp, the field that changed, and the complete before/after domain state. + + Args: + query: The apex domain name to retrieve history for (e.g. "domaintools.com"). + include_fields: Comma-separated list of exact field names. Only change events + matching these fields appear in results. Cannot be combined with + exclude_fields. Supports aggregate prefixes (e.g. "all_ssl", "all_ip"). + Example: "ip,registrar,all_ssl" + exclude_fields: Comma-separated list of exact field names. Change events + matching these fields are omitted. Cannot be combined with include_fields. + Example: "all_web_trackers,all_ssl" + page_size: Number of change events per page. Maximum and default is 100. + offset: 0-indexed starting point for pagination. Increment by page_size for + each subsequent page. + next: When True, includes a next URL in the response for cursor-based + pagination. Auth parameters must still be included when following it. + parsed_whois: When True, includes the full parsed WHOIS record in the + before/after objects of each change event. + parsed_domain_rdap: When True, includes the full parsed Domain RDAP record + in the before/after objects of each change event. + """ + return self._results( + "domain-history", + "/v1/domain-history", + domain=query, + include_fields=include_fields, + exclude_fields=exclude_fields, + page_size=page_size, + offset=offset, + next=next, + parsed_whois=parsed_whois, + parsed_domain_rdap=parsed_domain_rdap, + items_path=("changes",), + **kwargs, + ) + def domain_search( self, query, From 902a5d84df0affc02c36e5b45f8cdcf723ae8a7a Mon Sep 17 00:00:00 2001 From: JD Babac Date: Fri, 5 Jun 2026 01:01:02 +0800 Subject: [PATCH 2/3] IDEV-2478: Add tests --- test.py | 17 +++ tests/fixtures/vcr/test_domain_history.yaml | 136 ++++++++++++++++++++ tests/test_api.py | 16 +++ 3 files changed, 169 insertions(+) create mode 100644 test.py create mode 100644 tests/fixtures/vcr/test_domain_history.yaml diff --git a/test.py b/test.py new file mode 100644 index 0000000..8840dec --- /dev/null +++ b/test.py @@ -0,0 +1,17 @@ +import os + +from domaintools import API + +user = os.getenv("MY_API_USER", "jbabac") +key = os.getenv("MY_API_KEY") + +dt_api = API( + username=user, + key=key, + app_name="jd-test-python-wrapper", +) + +result = dt_api.iris_investigate("espn.com").data() +print(result) + +# help(dt_api.iris_investigate) diff --git a/tests/fixtures/vcr/test_domain_history.yaml b/tests/fixtures/vcr/test_domain_history.yaml new file mode 100644 index 0000000..5c9148f --- /dev/null +++ b/tests/fixtures/vcr/test_domain_history.yaml @@ -0,0 +1,136 @@ +interactions: +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + connection: + - keep-alive + host: + - api.domaintools.com + user-agent: + - python-httpx/0.22.0 + method: GET + uri: https://api.domaintools.com/v1/domain-history?app_name=python_wrapper&app_version=2.1.0&domain=chat.com&include_fields=registrar + response: + content: '{"response":{"domain":"chat.com","count":3,"registration_source":"parsed_whois","changes":[{"timestamp":"2024-03-15T12:00:00Z","field":"registrar","active":true,"before":{"domain":"chat.com","registrar":"Old + Registrar Inc","active":true},"after":{"domain":"chat.com","registrar":"New + Registrar LLC","active":true}},{"timestamp":"2023-06-20T08:30:00Z","field":"registrar","active":true,"before":{"domain":"chat.com","registrar":"Original + Registrar Co","active":true},"after":{"domain":"chat.com","registrar":"Old Registrar + Inc","active":true}},{"timestamp":"2022-01-10T00:00:00Z","field":"registrar","active":true,"before":null,"after":{"domain":"chat.com","registrar":"Original + Registrar Co","active":true}}]}}' + headers: + Content-Type: + - application/json;charset=utf-8 + Date: + - Thu, 05 Jun 2025 12:00:00 GMT + http_version: HTTP/1.1 + status_code: 200 +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + connection: + - keep-alive + host: + - api.domaintools.com + user-agent: + - python-httpx/0.28.1 + method: GET + uri: https://api.domaintools.com/v1/account?app_name=python_wrapper&app_version=2.7.4 + response: + content: '{"response":{"account":{"api_username":"integrations_testing","active":true},"products":[{"id":"account-information","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"5","absolute_limit":null,"usage":{"today":"43","month":"236"},"expiration_date":null},{"id":"iris-investigate","per_month_limit":"10000","per_hour_limit":null,"per_minute_limit":"20","absolute_limit":null,"usage":{"today":"7","month":"11"},"expiration_date":null},{"id":"iris-enrich","per_month_limit":"20000","per_hour_limit":null,"per_minute_limit":"60","absolute_limit":null,"usage":{"today":"9","month":"79"},"expiration_date":null},{"id":"iris-detect-escalate-domains","per_month_limit":"1500","per_hour_limit":null,"per_minute_limit":"30","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"iris-detect-ignored-domains","per_month_limit":"1500","per_hour_limit":"10","per_minute_limit":"30","absolute_limit":null,"usage":{"today":"11","month":"83"},"expiration_date":null},{"id":"iris-detect-manage-watchlist-domains","per_month_limit":"1500","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"iris-detect-monitors","per_month_limit":"1500","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"2","month":"5"},"expiration_date":null},{"id":"iris-detect-new-domains","per_month_limit":"1500","per_hour_limit":"10","per_minute_limit":"30","absolute_limit":null,"usage":{"today":"11","month":"83"},"expiration_date":null},{"id":"iris-detect-watched-domains","per_month_limit":"1500","per_hour_limit":"10","per_minute_limit":"30","absolute_limit":null,"usage":{"today":"11","month":"83"},"expiration_date":null},{"id":"domain-profile","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"domain-search","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"500","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"hosting-history","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"ip-monitor","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"5","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"ip-registrant-monitor","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"5","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"iris","per_month_limit":"10000","per_hour_limit":null,"per_minute_limit":"10","absolute_limit":null,"usage":{"today":"7","month":"11"},"expiration_date":null},{"id":"reputation","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"reverse-ip","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"10","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"reverse-ip-whois","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"risk","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"risk-evidence","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"reverse-name-server","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"10","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"reverse-whois","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"10","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"mark-alert","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"5","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"parsed-whois","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"name-server-monitor","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"5","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"whois","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"whois-history","per_month_limit":"5000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"parsed-whois-live","per_month_limit":"120","per_hour_limit":null,"per_minute_limit":"5","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"registrant-alert","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"5","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"newly-active-domains-feed-(api)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"20","absolute_limit":null,"usage":{"today":"19","month":"163"},"expiration_date":null},{"id":"newly-observed-domains-feed-(api)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"20","absolute_limit":null,"usage":{"today":"234","month":"2040"},"expiration_date":null},{"id":"parsed-domain-rdap","per_month_limit":"50000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"1","month":"16"},"expiration_date":null},{"id":"domain-registration-data-access-protocol-feed-(api)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"20","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"real-time-domain-discovery-feed-(api)","per_month_limit":"100000","per_hour_limit":"120","per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"real-time-domain-discovery-feed-(s3)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"domain-registration-data-access-protocol-feed-(s3)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"newly-active-domains-feed-(s3)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"20","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"newly-observed-domains-feed-(s3)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"20","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"newly-observed-hosts-feed-(api)","per_month_limit":"100000","per_hour_limit":"120","per_minute_limit":"20","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"newly-observed-hosts-feed-(s3)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"20","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"real-time-domain-hotlist-(api)","per_month_limit":"100000","per_hour_limit":"120","per_minute_limit":"120","absolute_limit":null,"usage":{"today":"19","month":"163"},"expiration_date":null},{"id":"real-time-domain-hotlist-(s3)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"10","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"real-time-domain-risk-(api)","per_month_limit":"100000","per_hour_limit":"120","per_minute_limit":"120","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"real-time-domain-risk-(s3)","per_month_limit":"100000","per_hour_limit":null,"per_minute_limit":"10","absolute_limit":null,"usage":{"today":"0","month":"0"},"expiration_date":null},{"id":"domain-history","per_month_limit":"1000","per_hour_limit":null,"per_minute_limit":"120","absolute_limit":null,"usage":{"today":"1","month":"1"},"expiration_date":null}]}}' + headers: + access-control-allow-origin: + - '*' + cache-control: + - no-store, no-cache, must-revalidate + content-encoding: + - gzip + content-security-policy: + - 'default-src * data: blob: ''unsafe-eval'' ''unsafe-inline''' + content-type: + - application/json;charset=utf-8 + date: + - Thu, 04 Jun 2026 16:33:19 GMT + expires: + - Thu, 19 Nov 1981 08:52:00 GMT + pragma: + - no-cache + set-cookie: + - dtsession=u7uu2bjnp2e17nu0j1vfsktlc6qvlad61v16eodsukkkfgfk28m6r5dfda0eiqolvgfufbb5trv8qlsu5nkmm2tjd95ovg2k6htvv0c; + expires=Sat, 04-Jul-2026 16:33:19 GMT; Max-Age=2592000; path=/; domain=.domaintools.com; + secure; HttpOnly + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-time: + - '195782' + http_version: HTTP/1.1 + status_code: 200 +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + connection: + - keep-alive + host: + - api.domaintools.com + user-agent: + - python-httpx/0.28.1 + method: GET + uri: https://api.domaintools.com/v1/domain-history?app_name=python_wrapper&app_version=2.7.4&domain=chat.com&include_fields=registrar + response: + content: '{"response":{"domain":"chat.com","count":8,"registration_source":"parsed_whois","changes":[{"timestamp":"2025-04-02T18:35:11Z","field":"registrar","before":{"registrar":{"value":"MarkMonitor + Inc."}},"after":{"registrar":{"value":"MarkMonitor, Inc."}}},{"timestamp":"2025-04-02T06:22:55Z","field":"registrar","before":{"registrar":{"value":"MarkMonitor, + Inc."}},"after":{"registrar":{"value":"MarkMonitor Inc."}}},{"timestamp":"2025-03-10T03:00:52Z","field":"registrar","before":{"registrar":{"value":"MarkMonitor + Inc."}},"after":{"registrar":{"value":"MarkMonitor, Inc."}}},{"timestamp":"2025-03-08T02:03:00Z","field":"registrar","before":{"registrar":{"value":"MarkMonitor, + Inc."}},"after":{"registrar":{"value":"MarkMonitor Inc."}}},{"timestamp":"2025-02-25T23:09:51Z","field":"registrar","before":{"registrar":{"value":"MarkMonitor + Inc."}},"after":{"registrar":{"value":"MarkMonitor, Inc."}}},{"timestamp":"2025-02-24T21:26:45Z","field":"registrar","before":{"registrar":{"value":"MarkMonitor, + Inc."}},"after":{"registrar":{"value":"MarkMonitor Inc."}}},{"timestamp":"2024-11-14T07:03:50Z","field":"registrar","before":{"registrar":{"value":"GoDaddy.com, + LLC"}},"after":{"registrar":{"value":"MarkMonitor, Inc."}}},{"timestamp":"2023-03-27T02:47:30Z","field":"registrar","before":{"registrar":{"value":"NET + TUNER CORP. DBA WEBMASTERS.COM"}},"after":{"registrar":{"value":"GoDaddy.com, + LLC"}}}]}}' + headers: + access-control-allow-origin: + - '*' + cache-control: + - no-store, no-cache, must-revalidate + content-encoding: + - gzip + content-security-policy: + - 'default-src * data: blob: ''unsafe-eval'' ''unsafe-inline''' + content-type: + - application/json;charset=utf-8 + date: + - Thu, 04 Jun 2026 16:33:20 GMT + expires: + - Thu, 19 Nov 1981 08:52:00 GMT + pragma: + - no-cache + set-cookie: + - dtsession=oheuhpln3atkp1d8fcpsc7dtjf47ous1cv908vf6ta7jeuvbdr6dmvk2jj8rlb6kfpc2khifdve0l2o9fuefg0m2rgf0kic4nc73hoi; + expires=Sat, 04-Jul-2026 16:33:20 GMT; Max-Age=2592000; path=/; domain=.domaintools.com; + secure; HttpOnly + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-time: + - '372678' + http_version: HTTP/1.1 + status_code: 200 +version: 1 diff --git a/tests/test_api.py b/tests/test_api.py index a74f2aa..6c8c2ef 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -70,6 +70,22 @@ def test_domain_profile(): assert "ip_address" in history +@vcr.use_cassette +def test_domain_history(): + api_call = api.domain_history("chat.com", include_fields="registrar") + with api_call as result: + assert "domain" in result + assert "count" in result + assert "registration_source" in result + assert "changes" in result + + for change in api_call: + assert "timestamp" in change + assert "field" in change + assert "before" in change + assert "after" in change + + @vcr.use_cassette def test_domain_search(): api_call = api.domain_search("google") From 406fb4fbeaba04d1f8213a4cc88c29613d2e218d Mon Sep 17 00:00:00 2001 From: JD Babac Date: Fri, 5 Jun 2026 01:01:48 +0800 Subject: [PATCH 3/3] IDEV-2478: Implement cli for domain-history. --- domaintools/cli/commands/domains.py | 46 +++++++++++++++++++++++++++++ domaintools/cli/constants.py | 1 + domaintools/cli/utils.py | 1 + test.py | 17 ----------- 4 files changed, 48 insertions(+), 17 deletions(-) delete mode 100644 test.py diff --git a/domaintools/cli/commands/domains.py b/domaintools/cli/commands/domains.py index 6ba401a..84e6a59 100644 --- a/domaintools/cli/commands/domains.py +++ b/domaintools/cli/commands/domains.py @@ -87,6 +87,51 @@ def domain_profile( DTCLICommand.run(name=c.DOMAIN_PROFILE, params=ctx.params) +@dt_cli.command( + name=c.DOMAIN_HISTORY, + help=get_cli_helptext_by_name(command_name=c.DOMAIN_HISTORY), +) +def domain_history( + ctx: typer.Context, + query: str = typer.Option(..., "-q", "--query", help="The apex domain name to retrieve history for (e.g. domaintools.com)."), + include_fields: str = typer.Option(None, "--include-fields", help="Comma-separated list of exact field names. Only change events matching these fields appear in results. Cannot be combined with --exclude-fields. Example: ip,registrar,all_ssl"), + exclude_fields: str = typer.Option(None, "--exclude-fields", help="Comma-separated list of exact field names. Change events matching these fields are omitted. Cannot be combined with --include-fields. Example: all_web_trackers,all_ssl"), + page_size: int = typer.Option(None, "--page-size", help="Number of change events per page. Maximum is 100 (default: 100)."), + offset: int = typer.Option(None, "--offset", help="0-indexed starting point for pagination. Increment by page-size for each subsequent page."), + next: bool = typer.Option(None, "--next", help="When true, includes a next URL in the response for cursor-based pagination."), + parsed_whois: bool = typer.Option(None, "--parsed-whois", help="When true, includes the full parsed WHOIS record in the before/after objects of each change event."), + parsed_domain_rdap: bool = typer.Option(None, "--parsed-domain-rdap", help="When true, includes the full parsed Domain RDAP record in the before/after objects of each change event."), + user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."), + key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"), + creds_file: str = typer.Option( + "~/.dtapi", + "-c", + "--credfile", + help="Optional file with API username and API key, one per line.", + ), + rate_limit: bool = typer.Option( + False, + "-l", + "--rate-limit", + help="Rate limit API calls against the API based on per minute limits.", + ), + format: str = typer.Option( + "json", + "-f", + "--format", + help="Output format in {'list', 'json', 'xml', 'html'}", + callback=DTCLICommand.validate_format_input, + ), + out_file: typer.FileTextWrite = typer.Option(sys.stdout, "-o", "--out-file", help="Output file (defaults to stdout)"), + no_verify_ssl: bool = typer.Option( + False, + "--no-verify-ssl", + help="Skip verification of SSL certificate when making HTTPs API calls", + ), +): + DTCLICommand.run(name=c.DOMAIN_HISTORY, params=ctx.params) + + @dt_cli.command( name=c.DOMAIN_SEARCH, help=get_cli_helptext_by_name(command_name=c.DOMAIN_SEARCH), @@ -666,6 +711,7 @@ def risk_evidence( __all__ = [ "brand_monitor", + "domain_history", "domain_profile", "domain_search", "name_server_monitor", diff --git a/domaintools/cli/constants.py b/domaintools/cli/constants.py index 6d42a7a..190a6af 100644 --- a/domaintools/cli/constants.py +++ b/domaintools/cli/constants.py @@ -4,6 +4,7 @@ # domains BRAND_MONITOR = "brand_monitor" +DOMAIN_HISTORY = "domain_history" DOMAIN_PROFILE = "domain_profile" DOMAIN_SEARCH = "domain_search" HOSTING_HISTORY = "hosting_history" diff --git a/domaintools/cli/utils.py b/domaintools/cli/utils.py index eafbd6b..81b3dcb 100644 --- a/domaintools/cli/utils.py +++ b/domaintools/cli/utils.py @@ -35,6 +35,7 @@ def _iris_investigate_helptext(): c.IRIS_INVESTIGATE: _iris_investigate_helptext(), c.IRIS_ENRICH: "Returns back enriched data related to the specified domains using our Iris Enrich service.", c.BRAND_MONITOR: "Pass in one or more terms as a list or separated by the pipe character ( | )", + c.DOMAIN_HISTORY: "Returns the history of changes for a given domain name.", c.DOMAIN_PROFILE: "Returns a profile for the specified domain name", c.DOMAIN_SEARCH: """Each term in the query string must be at least three characters long. Pass in a list or use spaces to separate multiple terms.""", c.HOSTING_HISTORY: "Returns the hosting history from the given domain name.", diff --git a/test.py b/test.py deleted file mode 100644 index 8840dec..0000000 --- a/test.py +++ /dev/null @@ -1,17 +0,0 @@ -import os - -from domaintools import API - -user = os.getenv("MY_API_USER", "jbabac") -key = os.getenv("MY_API_KEY") - -dt_api = API( - username=user, - key=key, - app_name="jd-test-python-wrapper", -) - -result = dt_api.iris_investigate("espn.com").data() -print(result) - -# help(dt_api.iris_investigate)