APIVoid

APIVoid wraps up a number of services such as ipvoid & urlvoid.

Data Enrichment & Threat Intelligence · APIVoid

Details

IDAPIVoid
ProviderAPIVoid
CategoryData Enrichment & Threat Intelligence
From Version5.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

APIVoid wraps up a number of services such as ipvoid & urlvoid.

Configure APIVoid in Cortex

Parameter Description Required
Server URL   True
API Key   False
Suspicious Reputation (Percentage) If the percentage of detections is above this value, the indicator is scored as SUSPICIOUS. If the percentage of detections is below this value, the indicator is scored as GOOD. True
Bad Reputation (Percentage) If the percentage of detections is above this value, the indicator is considered bad. True
Malicious The indicator is considered malicious if the suspicious or bad reputation percentages exceed the thresholds. True
Trust any certificate (not secure)   False
Use system proxy settings   False
Source Reliability Reliability of the source providing the intelligence data. False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

apivoid-ip


Returns the reputation and extended context of the IP.

Base Command

apivoid-ip

Input

Argument Name Description Required
ip The IP to query. Required

Context Output

Path Type Description
IP.Address string IP address
IP.DetectionEngines number The total number of engines that checked the indicator.
IP.Geo unknown  
IP.Geo.Country string The country in which the IP address is located.
IP.Geo.Description string Additional information about the location.
IP.Geo.Location string The geolocation where the IP address is located, in the format: latitude:longitude.
IP.Hostname string The hostname that is mapped to this IP address.
IP.PositiveDetections number The number of engines that positively detected the indicator as malicious.
DBotScore unknown  
DBotScore.Indicator string The indicator that was tested.
DBotScore.Score number The actual score.
DBotScore.Type string The indicator type.
DBotScore.Vendor string The vendor used to calculate the score.
APIVoid.IP.anonymity.is_hosting boolean  
APIVoid.IP.anonymity.is_proxy boolean  
APIVoid.IP.anonymity.is_tor boolean  
APIVoid.IP.anonymity.is_vpn boolean  
APIVoid.IP.anonymity.is_webproxy boolean  
APIVoid.IP.blacklists.detection_rate string  
APIVoid.IP.blacklists.detections number  
APIVoid.IP.blacklists.engines.detected boolean  
APIVoid.IP.blacklists.engines.elapsed string  
APIVoid.IP.blacklists.engines.engine string  
APIVoid.IP.blacklists.engines.reference string  
APIVoid.IP.blacklists.engines_count number  
APIVoid.IP.blacklists.scantime string  
APIVoid.IP.information.isp string  
APIVoid.IP.information.latitude string  
APIVoid.IP.information.reverse_dns string  
APIVoid.IP.information.longitude string  
APIVoid.IP.information.country_calling_code string  
APIVoid.IP.information.country_name string  
APIVoid.IP.information.region_name string  
APIVoid.IP.information.country_code string  
APIVoid.IP.information.continent_name string  
APIVoid.IP.information.continent_code string  
APIVoid.IP.information.country_currency string  
APIVoid.IP.information.city_name string  
APIVoid.IP.ip string  

apivoid-domain


Returns the reputation of the domain.

Base Command

apivoid-domain

Input

Argument Name Description Required
domain The Domain to query. Required

Context Output

Path Type Description
Domain unknown  
Domain.DNS string A list of IP objects resolved by DNS.
Domain.DetectionEngines number The total number of engines that checked the indicator.
Domain.Name string The domain name, for example: “google.com”.
Domain.PositiveDetections number The number of engines that positively detected the indicator as malicious.
DBotScore unknown  
DBotScore.Indicator string The indicator that was tested.
DBotScore.Score number The actual score.
DBotScore.Type string The indicator type.
DBotScore.Vendor string The vendor used to calculate the score.
APIVoid.Domain.alexa_top_100k boolean  
APIVoid.Domain.domain_length number  
APIVoid.Domain.server.isp string  
APIVoid.Domain.server.ip string  
APIVoid.Domain.server.latitude string  
APIVoid.Domain.server.reverse_dns string  
APIVoid.Domain.server.longitude string  
APIVoid.Domain.server.country_name string  
APIVoid.Domain.server.region_name string  
APIVoid.Domain.server.country_code string  
APIVoid.Domain.server.continent_name string  
APIVoid.Domain.server.continent_code string  
APIVoid.Domain.server.city_name string  
APIVoid.Domain.alexa_top_250k boolean  
APIVoid.Domain.alexa_top_10k boolean  
APIVoid.Domain.most_abused_tld boolean  
APIVoid.Domain.host string  
APIVoid.Domain.blacklists.detection_rate string  
APIVoid.Domain.blacklists.detections number  
APIVoid.Domain.blacklists.engines.confidence string  
APIVoid.Domain.blacklists.engines.detected boolean  
APIVoid.Domain.blacklists.engines.elapsed string  
APIVoid.Domain.blacklists.engines.engine string  
APIVoid.Domain.blacklists.engines.reference string  
APIVoid.Domain.blacklists.engines_count number  
APIVoid.Domain.blacklists.scantime string  
APIVoid.Domain.category.is_anonymizer boolean  
APIVoid.Domain.category.is_free_dynamic_dns boolean  
APIVoid.Domain.category.is_free_hosting boolean  
APIVoid.Domain.category.is_url_shortener boolean  

apivoid-url


Returns the reputation of the URL.

Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.

Base Command

apivoid-url

Input

Argument Name Description Required
url The URL to query. Required

Context Output

Path Type Description
URL unknown  
URL.Data string The URL
URL.DetectionEngines number The total number of engines that checked the indicator.
URL.PositiveDetections number The number of engines that positively detected the indicator as malicious.
DBotScore unknown  
DBotScore.Indicator string The indicator that was tested.
DBotScore.Score number The actual score.
DBotScore.Type string The indicator type.
DBotScore.Vendor string The vendor used to calculate the score.
APIVoid.URL.risk_score.result number  
APIVoid.URL.domain_blacklist.detections number  
APIVoid.URL.domain_blacklist.engines.detected boolean  
APIVoid.URL.domain_blacklist.engines.name string  
APIVoid.URL.domain_blacklist.engines.reference string  
APIVoid.URL.geo_location.countries string  
APIVoid.URL.server_details.isp string  
APIVoid.URL.server_details.ip string  
APIVoid.URL.server_details.latitude string  
APIVoid.URL.server_details.longitude string  
APIVoid.URL.server_details.hostname string  
APIVoid.URL.server_details.country_name string  
APIVoid.URL.server_details.region_name string  
APIVoid.URL.server_details.country_code string  
APIVoid.URL.server_details.continent_name string  
APIVoid.URL.server_details.continent_code string  
APIVoid.URL.server_details.city_name string  
APIVoid.URL.response_headers.server string  
APIVoid.URL.response_headers.code number  
APIVoid.URL.response_headers.content-type string  
APIVoid.URL.response_headers.date date  
APIVoid.URL.response_headers.cache-control string  
APIVoid.URL.response_headers.host-header string  
APIVoid.URL.response_headers.status string  
APIVoid.URL.response_headers.x-redirect-by string  
APIVoid.URL.response_headers.expires date  
APIVoid.URL.response_headers.location string  
APIVoid.URL.response_headers.content-length string  
APIVoid.URL.response_headers.upgrade string  
APIVoid.URL.response_headers.connection string  
APIVoid.URL.security_checks.is_windows_exe_file_on_ipv4 boolean  
APIVoid.URL.security_checks.is_credit_card_form boolean  
APIVoid.URL.security_checks.is_windows_exe_file_on_free_hosting boolean  
APIVoid.URL.security_checks.is_linux_elf_file_on_ipv4 boolean  
APIVoid.URL.security_checks.is_linux_elf_file_on_free_hosting boolean  
APIVoid.URL.security_checks.is_masked_windows_exe_file boolean  
APIVoid.URL.security_checks.is_zip_on_directory_listing boolean  
APIVoid.URL.security_checks.is_masked_linux_elf_file boolean  
APIVoid.URL.security_checks.is_sinkholed_domain boolean  
APIVoid.URL.security_checks.is_suspended_page boolean  
APIVoid.URL.security_checks.is_suspicious_file_extension boolean  
APIVoid.URL.security_checks.is_uncommon_clickable_url boolean  
APIVoid.URL.security_checks.is_suspicious_content boolean  
APIVoid.URL.security_checks.is_risky_geo_location boolean  
APIVoid.URL.security_checks.is_php_on_directory_listing boolean  
APIVoid.URL.security_checks.is_doc_on_directory_listing boolean  
APIVoid.URL.security_checks.is_doc_on_directory_listing boolean  
APIVoid.URL.security_checks.is_empty_page_title boolean  
APIVoid.URL.security_checks.is_login_form boolean  
APIVoid.URL.security_checks.is_robots_noindex boolean  
APIVoid.URL.security_checks.is_suspicious_domain boolean  
APIVoid.URL.security_checks.is_windows_exe_file_on_free_dynamic_dns boolean  
APIVoid.URL.security_checks.is_most_abused_tld boolean  
APIVoid.URL.security_checks.is_linux_elf_file_on_free_dynamic_dns boolean  
APIVoid.URL.security_checks.is_suspicious_url_pattern boolean  
APIVoid.URL.security_checks.is_valid_https boolean  
APIVoid.URL.security_checks.is_exe_on_directory_listing boolean  
APIVoid.URL.security_checks.is_pdf_on_directory_listing boolean  
APIVoid.URL.security_checks.is_host_an_ipv4 boolean  
APIVoid.URL.security_checks.is_domain_blacklisted boolean  
APIVoid.URL.security_checks.is_china_country boolean  
APIVoid.URL.security_checks.is_windows_exe_file boolean  
APIVoid.URL.security_checks.is_masked_file boolean  
APIVoid.URL.security_checks.is_email_address_on_url_query boolean  
APIVoid.URL.security_checks.is_phishing_heuristic boolean  
APIVoid.URL.security_checks.is_non_standard_port boolean  
APIVoid.URL.security_checks.is_linux_elf_file boolean  
APIVoid.URL.security_checks.is_defaced_heuristic boolean  
APIVoid.URL.security_checks.is_directory_listing boolean  
APIVoid.URL.dns_records.mx.records.country_code string  
APIVoid.URL.dns_records.ns.records.country_name string  
APIVoid.URL.dns_records.ns.records.ip string  
APIVoid.URL.dns_records.ns.records.isp string  
APIVoid.URL.dns_records.ns.records.target string  
APIVoid.URL.redirection.external boolean  
APIVoid.URL.redirection.found boolean  
APIVoid.URL.redirection.url string  
APIVoid.URL.url string  
APIVoid.URL.url_parts.host string  
APIVoid.URL.url_parts.host_nowww string  
APIVoid.URL.url_parts.path string  
APIVoid.URL.url_parts.port number  
APIVoid.URL.url_parts.query string  
APIVoid.URL.url_parts.scheme string  
APIVoid.URL.site_category.is_anonymizer boolean  
APIVoid.URL.site_category.is_free_dynamic_dns boolean  
APIVoid.URL.site_category.is_free_hosting boolean  
APIVoid.URL.site_category.is_torrent boolean  
APIVoid.URL.site_category.is_url_shortener boolean  
APIVoid.URL.site_category.is_vpn_provider boolean  
APIVoid.URL.web_page.description string  
APIVoid.URL.web_page.keywords string  
APIVoid.URL.web_page.title string  
APIVoid.URL.html_forms.credit_card_field_present boolean  
APIVoid.URL.html_forms.email_field_present boolean  
APIVoid.URL.html_forms.number_of_total_forms number  
APIVoid.URL.html_forms.number_of_total_input_fields number  
APIVoid.URL.html_forms.password_field_present boolean  
APIVoid.URL.html_forms.two_text_inputs_in_a_form boolean  
APIVoid.URL.file_type.extension string  
APIVoid.URL.file_type.headers string  
APIVoid.URL.file_type.signature string  

ip


Returns the reputation of the IP.

Base Command

ip

Input

Argument Name Description Required
ip The IP to query. Required

Context Output

Path Type Description
IP unknown  
IP.Address string IP address
IP.DetectionEngines number The total number of engines that checked the indicator.
IP.Geo unknown  
IP.Geo.Country string The country in which the IP address is located.
IP.Geo.Description string Additional information about the location.
IP.Geo.Location string The geolocation where the IP address is located, in the format: latitude:longitude.
IP.Hostname string The hostname that is mapped to this IP address.
IP.PositiveDetections number The number of engines that positively detected the indicator as malicious.
DBotScore.Indicator string The indicator that was tested.
DBotScore.Score number The actual score.
DBotScore.Type string The indicator type.
DBotScore.Vendor string The vendor used to calculate the score.

domain


Returns the reputation of the domain.

Base Command

domain

Input

Argument Name Description Required
domain The Domain to query. Required

Context Output

Path Type Description
Domain.DNS string A list of IP objects resolved by DNS.
Domain.DetectionEngines number The total number of engines that checked the indicator.
Domain.Name string The domain name, for example: “google.com”.
Domain.PositiveDetections number The number of engines that positively detected the indicator as malicious.
DBotScore.Indicator string The indicator that was tested.
DBotScore.Score number The actual score.
DBotScore.Type string The indicator type.
DBotScore.Vendor string The vendor used to calculate the score.

url


Returns the reputation of the URL.

Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.

Base Command

url

Input

Argument Name Description Required
url The URL to query. Required

Context Output

Path Type Description
URL.Data string The URL
URL.DetectionEngines number The total number of engines that checked the indicator.
URL.PositiveDetections number The number of engines that positively detected the indicator as malicious.
URL.RiskScore number  
URL.Score string  
DBotScore unknown  
DBotScore.Indicator string The indicator that was tested.
DBotScore.Score number The actual score.
DBotScore.Type string The indicator type.
DBotScore.Vendor string The vendor used to calculate the score.

apivoid-dns-lookup


Gets DNS records of a host.

Base Command

apivoid-dns-lookup

Input

Argument Name Description Required
host Host to lookup. Required
type The DNS record type to lookup. Possible values are: A, AAAA, MX, NS, DMARK, Reverse, TXT, ANY, CNAME, SOA, SRV, CAA. Default is A. Required

Context Output

Path Type Description
APIVoid.DNS unknown  
APIVoid.DNS.items.host string  
APIVoid.DNS.items.class string  
APIVoid.DNS.items.ttl number  
APIVoid.DNS.items.type string  
APIVoid.DNS.items.ip string  
APIVoid.DNS.found boolean  
APIVoid.DNS.count number  
APIVoid.DNS.items.ipv6 string  
APIVoid.DNS.items.pri number  
APIVoid.DNS.items.target string  
APIVoid.DNS.items.txt string  
APIVoid.DNS.items.entries unknown  
APIVoid.DNS.items.mname string  
APIVoid.DNS.items.rname string  
APIVoid.DNS.items.serial number  
APIVoid.DNS.items.refresh number  
APIVoid.DNS.items.retry number  
APIVoid.DNS.items.expire number  
APIVoid.DNS.items.minimum-ttl number  
APIVoid.DNS.items.weight number  
APIVoid.DNS.items.port number  
APIVoid.DNS.items.flags number  
APIVoid.DNS.items.tag string  
APIVoid.DNS.items.value string  

apivoid-ssl-info


Get useful SSL information from a remote host

Base Command

apivoid-ssl-info

Input

Argument Name Description Required
host Host to lookup SSL. Required

Context Output

Path Type Description
APIVoid.SSL unknown  
APIVoid.SSL.found boolean  
APIVoid.SSL.fingerprint string  
APIVoid.SSL.deprecated_issuer boolean  
APIVoid.SSL.expired boolean  
APIVoid.SSL.valid_peer boolean  
APIVoid.SSL.host string  
APIVoid.SSL.name_match boolean  
APIVoid.SSL.debug_message string  
APIVoid.SSL.blacklisted boolean  
APIVoid.SSL.valid boolean  
APIVoid.SSL.details unknown  
APIVoid.SSL.details.extensions unknown  
APIVoid.SSL.details.extensions.authority_info_access string  
APIVoid.SSL.details.extensions.authority_key_identifier string  
APIVoid.SSL.details.extensions.basic_constraints string  
APIVoid.SSL.details.extensions.certificate_policies string  
APIVoid.SSL.details.extensions.crl_distribution_points string  
APIVoid.SSL.details.extensions.extended_key_usage string  
APIVoid.SSL.details.extensions.key_usage string  
APIVoid.SSL.details.extensions.subject_key_identifier string  
APIVoid.SSL.details.hash string  
APIVoid.SSL.details.issuer unknown  
APIVoid.SSL.details.issuer.common_name string  
APIVoid.SSL.details.issuer.country string  
APIVoid.SSL.details.issuer.location string  
APIVoid.SSL.details.issuer.organization string  
APIVoid.SSL.details.issuer.organization_unit string  
APIVoid.SSL.details.issuer.state string  
APIVoid.SSL.details.signature unknown  
APIVoid.SSL.details.signature.serial string  
APIVoid.SSL.details.signature.serial_hex string  
APIVoid.SSL.details.signature.type string  
APIVoid.SSL.details.subject unknown  
APIVoid.SSL.details.subject.postal_code string  
APIVoid.SSL.details.subject.street string  
APIVoid.SSL.details.subject.name string  
APIVoid.SSL.details.subject.organization_unit string  
APIVoid.SSL.details.subject.state string  
APIVoid.SSL.details.subject.organization string  
APIVoid.SSL.details.subject.location string  
APIVoid.SSL.details.subject.alternative_names string  
APIVoid.SSL.details.subject.country string  
APIVoid.SSL.details.subject.category string  
APIVoid.SSL.details.subject.common_name string  
APIVoid.SSL.details.validity unknown  
APIVoid.SSL.details.validity.days_left number  
APIVoid.SSL.details.validity.valid_from date  
APIVoid.SSL.details.validity.valid_from_timestamp date  
APIVoid.SSL.details.validity.valid_to date  
APIVoid.SSL.details.validity.valid_to_timestamp date  
APIVoid.SSL.details.version string  

apivoid-email-verify


Checks if an email address is disposable, if it has MX records, and more.

Base Command

apivoid-email-verify

Input

Argument Name Description Required
email Email address to lookup. Required

Context Output

Path Type Description
APIVoid.Email unknown  
APIVoid.Email.email string  
APIVoid.Email.valid_format boolean  
APIVoid.Email.username string  
APIVoid.Email.role_address boolean  
APIVoid.Email.suspicious_username boolean  
APIVoid.Email.dirty_words_username boolean  
APIVoid.Email.domain string  
APIVoid.Email.valid_tld boolean  
APIVoid.Email.disposable boolean  
APIVoid.Email.has_mx_records boolean  
APIVoid.Email.free_email boolean  
APIVoid.Email.russian_free_email boolean  
APIVoid.Email.china_free_email boolean  
APIVoid.Email.suspicious_domain boolean  
APIVoid.Email.did_you_mean string  
APIVoid.Email.dirty_words_domain boolean  
APIVoid.Email.domain_popular boolean  
APIVoid.Email.risky_tld boolean  
APIVoid.Email.police_domain boolean  
APIVoid.Email.government_domain boolean  
APIVoid.Email.educational_domain boolean  
APIVoid.Email.should_block boolean  
APIVoid.Email.score number  

apivoid-threatlog


Check if a website is present on ThreatLog database

Base Command

apivoid-threatlog

Input

Argument Name Description Required
host The host the check. Required

Context Output

Path Type Description
APIVoid.ThreatLog.detected boolean  
APIVoid.ThreatLog.host string  
APIVoid.ThreatLog.scantime string  
Domain.Name string The domain name, for example: “google.com”.

apivoid-parked-domain


Detect if a domain (i.e google.com) is actually parked

Base Command

apivoid-parked-domain

Input

Argument Name Description Required
domain Domain to check. Required

Context Output

Path Type Description
APIVoid.ParkedDomain.host string  
APIVoid.ParkedDomain.parked_domain boolean  
Domain.Name string The domain name, for example: “google.com”.

apivoid-domain-age


Get the registration date of a domain and the domain age in days

Base Command

apivoid-domain-age

Input

Argument Name Description Required
domain The domain to check. Required

Context Output

Path Type Description
APIVoid.DomainAge.debug_message string  
APIVoid.DomainAge.domain_age_found boolean  
APIVoid.DomainAge.domain_age_in_days number  
APIVoid.DomainAge.domain_age_in_months number  
APIVoid.DomainAge.domain_age_in_years number  
APIVoid.DomainAge.domain_creation_date string  
APIVoid.DomainAge.domain_registered string  
APIVoid.DomainAge.host string  
Domain.CreationDate date The date that the domain was created.
Domain.Name string The domain name, for example: “google.com”.

apivoid-url-to-image


Capture a high-quality screenshot of any website or URL

Base Command

apivoid-url-to-image

Input

Argument Name Description Required
url URL to capture screenshot of. Required

Context Output

Path Type Description
File.Size number The size of the file.
File.SHA1 string The SHA1 hash of the file.
File.SHA256 string The SHA256 hash of the file.
File.SHA512 string The SHA512 hash of the file.
File.Name string The name of the file.
File.SSDeep string The SSDeep hash of the file.
File.EntryID string The EntryID of the file.
File.Info string Info regarding the file.
File.Type string The type of the file.
File.MD5 string The MD5 hash of the file.
File.Extension string The extension of the file.

apivoid-url-to-pdf


Convert an URL info high-quality and printable PDF document

Base Command

apivoid-url-to-pdf

Input

Argument Name Description Required
url URL to create PDF of. Required

Context Output

Path Type Description
File.Size number The size of the file.
File.SHA1 string The SHA1 hash of the file.
File.SHA256 string The SHA256 hash of the file.
File.SHA512 string The SHA512 hash of the file.
File.Name string The name of the file.
File.SSDeep string The SSDeep hash of the file.
File.EntryID string The EntryID of the file.
File.Info string Info regarding the file.
File.Type string The type of the file.
File.MD5 string The MD5 hash of the file.
File.Extension string The extension of the file.

apivoid-url-to-html


Get the body of an html page after javascript has been executed

Base Command

apivoid-url-to-html

Input

Argument Name Description Required
url URL to create PDF of. Required

Context Output

Path Type Description
File.Size number The size of the file.
File.SHA1 string The SHA1 hash of the file.
File.SHA256 string The SHA256 hash of the file.
File.SHA512 string The SHA512 hash of the file.
File.Name string The name of the file.
File.SSDeep string The SSDeep hash of the file.
File.EntryID string The EntryID of the file.
File.Info string Info regarding the file.
File.Type string The type of the file.
File.MD5 string The MD5 hash of the file.
File.Extension string The extension of the file.

apivoid-site-trustworthiness


A smart API that accurately checks a website’s trustworthiness.

Base Command

apivoid-site-trustworthiness

Input

Argument Name Description Required
host The host to check. Required

Context Output

Path Type Description
APIVoid.SiteTrust.domain_blacklist.detections number  
APIVoid.SiteTrust.domain_blacklist.engines.detected boolean  
APIVoid.SiteTrust.domain_blacklist.engines.name string  
APIVoid.SiteTrust.domain_blacklist.engines.reference string  
APIVoid.SiteTrust.geo_location.countries unknown  
APIVoid.SiteTrust.domain_age.domain_age_in_days number  
APIVoid.SiteTrust.domain_age.domain_age_in_months number  
APIVoid.SiteTrust.domain_age.domain_age_in_years number  
APIVoid.SiteTrust.domain_age.domain_creation_date string  
APIVoid.SiteTrust.domain_age.found boolean  
APIVoid.SiteTrust.server_details.isp string  
APIVoid.SiteTrust.server_details.ip string  
APIVoid.SiteTrust.server_details.latitude number  
APIVoid.SiteTrust.server_details.longitude number  
APIVoid.SiteTrust.server_details.hostname string  
APIVoid.SiteTrust.server_details.country_name string  
APIVoid.SiteTrust.server_details.region_name string  
APIVoid.SiteTrust.server_details.country_code string  
APIVoid.SiteTrust.server_details.continent_name string  
APIVoid.SiteTrust.server_details.continent_code string  
APIVoid.SiteTrust.server_details.city_name string  
APIVoid.SiteTrust.response_headers.server string  
APIVoid.SiteTrust.response_headers.content-encoding string  
APIVoid.SiteTrust.response_headers.code number  
APIVoid.SiteTrust.response_headers.content-type string  
APIVoid.SiteTrust.response_headers.date date  
APIVoid.SiteTrust.response_headers.vary string  
APIVoid.SiteTrust.response_headers.status string  
APIVoid.SiteTrust.response_headers.x-amz-rid string  
APIVoid.SiteTrust.response_headers.content-length string  
APIVoid.SiteTrust.response_headers.connection string  
APIVoid.SiteTrust.host string  
APIVoid.SiteTrust.security_checks.is_website_popular boolean  
APIVoid.SiteTrust.security_checks.is_suspended_site boolean  
APIVoid.SiteTrust.security_checks.is_domain_recent string  
APIVoid.SiteTrust.security_checks.is_heuristic_pattern boolean  
APIVoid.SiteTrust.security_checks.is_sinkholed_domain boolean  
APIVoid.SiteTrust.security_checks.is_risky_geo_location boolean  
APIVoid.SiteTrust.security_checks.is_empty_page_title boolean  
APIVoid.SiteTrust.security_checks.is_robots_noindex boolean  
APIVoid.SiteTrust.security_checks.is_suspicious_domain boolean  
APIVoid.SiteTrust.security_checks.is_most_abused_tld boolean  
APIVoid.SiteTrust.security_checks.is_valid_https boolean  
APIVoid.SiteTrust.security_checks.is_domain_blacklisted boolean  
APIVoid.SiteTrust.security_checks.is_email_configured boolean  
APIVoid.SiteTrust.security_checks.is_china_country boolean  
APIVoid.SiteTrust.security_checks.is_directory_listing boolean  
APIVoid.SiteTrust.security_checks.is_free_email boolean  
APIVoid.SiteTrust.trust_score.result number  
APIVoid.SiteTrust.dns_records unknown  
APIVoid.SiteTrust.redirection.external boolean  
APIVoid.SiteTrust.redirection.found boolean  
APIVoid.SiteTrust.redirection.url string  
APIVoid.SiteTrust.url_parts.host string  
APIVoid.SiteTrust.url_parts.host_nowww string  
APIVoid.SiteTrust.url_parts.path string  
APIVoid.SiteTrust.url_parts.port string  
APIVoid.SiteTrust.url_parts.query string  
APIVoid.SiteTrust.url_parts.scheme string  
APIVoid.SiteTrust.ecommerce_platform.is_magento boolean  
APIVoid.SiteTrust.ecommerce_platform.is_opencart boolean  
APIVoid.SiteTrust.ecommerce_platform.is_prestashop boolean  
APIVoid.SiteTrust.ecommerce_platform.is_shopify boolean  
APIVoid.SiteTrust.ecommerce_platform.is_woocommerce boolean  
APIVoid.SiteTrust.ecommerce_platform.is_zencart boolean  
APIVoid.SiteTrust.web_page.description string  
APIVoid.SiteTrust.web_page.keywords string  
APIVoid.SiteTrust.web_page.title string  
APIVoid.SiteTrust.targeted_brands.patagonia boolean  
APIVoid.SiteTrust.targeted_brands.rolex boolean  
APIVoid.SiteTrust.targeted_brands.timberland boolean  
APIVoid.SiteTrust.targeted_brands.hugoboss boolean  
APIVoid.SiteTrust.targeted_brands.moncler boolean  
APIVoid.SiteTrust.targeted_brands.longchamp boolean  
APIVoid.SiteTrust.targeted_brands.abercrombie boolean  
APIVoid.SiteTrust.targeted_brands.montblanc boolean  
APIVoid.SiteTrust.targeted_brands.carhartt boolean  
APIVoid.SiteTrust.targeted_brands.rayban boolean  
APIVoid.SiteTrust.targeted_brands.drmartens boolean  
APIVoid.SiteTrust.targeted_brands.hermes boolean  
APIVoid.SiteTrust.targeted_brands.oakley boolean  
APIVoid.SiteTrust.targeted_brands.michaelkors boolean  
APIVoid.SiteTrust.targeted_brands.louisvuitton boolean  
APIVoid.SiteTrust.targeted_brands.birkenstock boolean  
APIVoid.SiteTrust.targeted_brands.adidas boolean  
APIVoid.SiteTrust.targeted_brands.vans boolean  
APIVoid.SiteTrust.targeted_brands.ralphlauren boolean  
APIVoid.SiteTrust.targeted_brands.mulberry boolean  
APIVoid.SiteTrust.targeted_brands.converse boolean  
APIVoid.SiteTrust.targeted_brands.versace boolean  
APIVoid.SiteTrust.targeted_brands.ugg boolean  
APIVoid.SiteTrust.targeted_brands.nike boolean  
APIVoid.SiteTrust.targeted_brands.swarovski boolean  
APIVoid.SiteTrust.targeted_brands.peuterey boolean  
APIVoid.SiteTrust.targeted_brands.cartier boolean  
APIVoid.SiteTrust.targeted_brands.pandora boolean  
APIVoid.SiteTrust.targeted_brands.burberry boolean  
APIVoid.SiteTrust.targeted_brands.gucci boolean  
APIVoid.SiteTrust.targeted_brands.salomon boolean  
APIVoid.SiteTrust.targeted_brands.liujo boolean  
APIVoid.SiteTrust.targeted_brands.truereligion boolean  

Configuration parameters

  • url — Server URL (required)
  • credentials
  • apikey — API KEY
  • suspicious — Suspicious Reputation (Percentage) (required)
  • bad — Bad Reputation (Percentage) (required)
  • malicious — Malicious (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • integrationReliability — Source Reliability
  • feedExpirationPolicy
  • feedExpirationInterval

Commands (16)

  • apivoid-dns-lookup

    Gets DNS records of a host.

  • apivoid-domain

    Returns the reputation of the domain.

  • apivoid-domain-age

    Get the registration date of a domain and the domain age in days

  • apivoid-email-verify

    Checks if an email address is disposable, if it has MX records, and more.

  • apivoid-ip

    Returns the reputation and extended context of the IP.

  • apivoid-parked-domain

    Detect if a domain (i.e google.com) is actually parked

  • apivoid-site-trustworthiness

    A smart API that accurately checks a website's trustworthiness.

  • apivoid-ssl-info

    Get useful SSL information from a remote host

  • apivoid-threatlog Deprecated

    Deprecated. This command is deprecated because it is not supported in API V2. Check if a website is present on ThreatLog database.

  • apivoid-url

    Returns the reputation of the URL.

  • apivoid-url-to-html Deprecated

    Deprecated. This command is deprecated because it is not supported in API V2. Get the body of an html page after javascript has been executed.

  • apivoid-url-to-image

    Capture a high-quality screenshot of any website or URL

  • apivoid-url-to-pdf

    Convert an URL info high-quality and printable PDF document

  • domain

    Returns the reputation of the domain.

  • ip

    Returns the reputation of the IP.

  • url

    Returns the reputation of the URL.

import demistomock as demisto
from CommonServerPython import *
from CommonServerUserPython import *

"""IMPORTS"""
import urllib3
from base64 import b64decode
from typing import Any

# Disable insecure warnings
urllib3.disable_warnings()

"""CONSTANTS"""
DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"

# V2 API Endpoints
ENDPOINTS = {
    "ip_reputation": "/v2/ip-reputation",
    "domain_reputation": "/v2/domain-reputation",
    "url_reputation": "/v2/url-reputation",
    "dns_lookup": "/v2/dns-lookup",
    "ssl_info": "/v2/ssl-info",
    "email_verify": "/v2/email-verify",
    "parked_domain": "/v2/parked-domain",
    "domain_age": "/v2/domain-age",
    "screenshot": "/v2/screenshot",
    "url_to_pdf": "/v2/url-to-pdf",
    "site_trustworthiness": "/v2/site-trust",
}

# Global field mapping - maps API V2 field names to YML expected field names
# This mapping is applied recursively to all response data
FIELD_MAPPING = {
    "elapsed_ms": "elapsed",
    "name": "engine",
    "calling_code": "country_calling_code",
    "currency": "country_currency",
    "scan_time_ms": "scantime",
    "html_info": "web_page",
    "fingerprint_sha1": "fingerprint",
}


class Client(BaseClient):
    """
    APIVoid V2 Client - handles all API requests with V2 authentication
    """

    def __init__(self, base_url: str, apikey: str, verify: bool, proxy: bool):
        headers = {"X-API-Key": apikey, "Content-Type": "application/json"}
        super().__init__(base_url, verify=verify, proxy=proxy, headers=headers)

    def api_request(self, endpoint: str, json_data: dict) -> dict:
        """Generic V2 API request method"""
        demisto.debug(f"APIVoid: Making API request to {endpoint} with data: {json_data}")

        response = self._http_request(method="POST", url_suffix=endpoint, json_data=json_data)
        demisto.debug(f"APIVoid: Received response with {len(response)} fields")
        return response


def map_fields(data: Any, exclude_mappings: list | None = None) -> Any:
    """
    Recursively map field names in a data structure according to FIELD_MAPPING.
    Works on dictionaries, lists, and nested structures.

    Args:
        data: Data structure to map (dict, list, or any other type)
        exclude_mappings: Optional list of field names to exclude from mapping

    Returns:
        Data structure with mapped field names
    """
    if isinstance(data, dict):
        # Create a new dict to avoid modifying during iteration
        result = {}
        for key, value in data.items():
            # Map the key if it exists in the global mapping and is not excluded
            if exclude_mappings and key in exclude_mappings:
                new_key = key
            else:
                new_key = FIELD_MAPPING.get(key, key)
            # Recursively process the value
            result[new_key] = map_fields(value, exclude_mappings)
        return result
    elif isinstance(data, list):
        # Recursively process each item in the list
        return [map_fields(item, exclude_mappings) for item in data]
    else:
        # Return primitive types as-is
        return data


def calculate_dbot_score(engines_count: int, detections: int, thresholds: dict) -> int:
    """
    Calculate DBot score based on detection rate

    Args:
        engines_count: Total number of engines
        detections: Number of positive detections
        thresholds: Dict with 'suspicious', 'bad' thresholds (%)

    Returns:
        DBot score (0-3)
    """
    if engines_count == 0:
        return Common.DBotScore.NONE

    detection_rate = (detections / engines_count) * 100

    if detection_rate > thresholds["bad"]:
        return Common.DBotScore.BAD
    if detection_rate > thresholds["suspicious"]:
        return Common.DBotScore.SUSPICIOUS

    return Common.DBotScore.GOOD


def ip_reputation_command(
    client: Client, args: dict, reputation_only: bool, thresholds: dict, reliability: str
) -> CommandResults:
    """
    Get IP reputation from APIVoid V2 API

    Args:
        client: APIVoid client instance
        args: Command arguments
        reputation_only: If True, return only standard IP context
        thresholds: Dict with 'good', 'suspicious', 'bad' thresholds
        reliability: Source reliability level

    Returns:
        CommandResults object
    """
    ip = args.get("ip")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["ip_reputation"], {"ip": ip})
    except Exception as e:
        raise DemistoException(f"Failed to get IP reputation: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error checking IP {ip}: {response.get("error")}')

    # Extract data
    blacklists = response.get("blacklists", {})
    information = response.get("information", {})
    engines_count = blacklists.get("engines_count", 0)
    detections = blacklists.get("detections", 0)

    # Convert engines dict to list for YML compatibility
    if "engines" in blacklists:
        engines_dict = blacklists["engines"]
        if isinstance(engines_dict, dict):
            engines_list = list(engines_dict.values())
            response["blacklists"]["engines"] = engines_list

    # Apply field mapping recursively to entire response
    response = map_fields(response)

    # Calculate DBot score
    score = calculate_dbot_score(engines_count, detections, thresholds)

    # Create DBot score object
    dbot_score = Common.DBotScore(
        indicator=ip,
        indicator_type=DBotScoreType.IP,
        integration_name="APIVoid",
        score=score,
        reliability=reliability,
        malicious_description=f"Detection rate of {detections}/{engines_count}",
    )

    # Create IP indicator with standard context
    lat = information.get("latitude")
    lng = information.get("longitude")

    ip_indicator = Common.IP(
        ip=ip,
        detection_engines=engines_count,
        positive_engines=detections,
        dbot_score=dbot_score,
        hostname=information.get("reverse_dns"),
        geo_country=information.get("country_name"),
        geo_description=information.get("isp"),
        geo_latitude=lat,
        geo_longitude=lng,
    )

    # Build custom context outputs
    outputs = None if reputation_only else response

    readable_data = {
        "Address": ip,
        "Hostname": information.get("reverse_dns"),
        "Geo": {
            "Location": f"{lat}:{lng}" if lat and lng else None,
            "Country": information.get("country_name"),
            "Description": information.get("isp"),
        },
        "DetectionEngines": engines_count,
        "PositiveDetections": detections,
    }

    readable_output = tableToMarkdown(f"APIVoid information for {ip}:", readable_data)

    return CommandResults(
        outputs_prefix="APIVoid.IP",
        outputs_key_field="ip",
        outputs=outputs,
        indicator=ip_indicator,
        readable_output=readable_output,
        raw_response=response,
    )


def domain_reputation_command(
    client: Client, args: dict, reputation_only: bool, thresholds: dict, reliability: str
) -> CommandResults:
    """
    Get Domain reputation from APIVoid V2 API

    Args:
        client: APIVoid client instance
        args: Command arguments
        reputation_only: If True, return only standard Domain context
        thresholds: Dict with 'good', 'suspicious', 'bad' thresholds
        reliability: Source reliability level

    Returns:
        CommandResults object
    """
    domain = args.get("domain")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["domain_reputation"], {"host": domain})
    except Exception as e:
        raise DemistoException(f"Failed to get domain reputation: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error checking domain {domain}: {response.get("error")}')

    # Map V2 response to V1 field names for YML compatibility
    if "server_details" in response:
        response["server"] = response.pop("server_details")

    # Extract data
    blacklists = response.get("blacklists", {})
    engines_count = blacklists.get("engines_count", 0)
    detections = blacklists.get("detections", 0)

    # Convert engines dict to list for YML compatibility
    if "engines" in blacklists:
        engines_dict = blacklists["engines"]
        if isinstance(engines_dict, dict):
            engines_list = list(engines_dict.values())
            response["blacklists"]["engines"] = engines_list

    # Apply field mapping recursively to entire response
    response = map_fields(response)

    # Calculate DBot score
    score = calculate_dbot_score(engines_count, detections, thresholds)

    # Create DBot score object
    dbot_score = Common.DBotScore(
        indicator=domain,
        indicator_type=DBotScoreType.DOMAIN,
        integration_name="APIVoid",
        score=score,
        reliability=reliability,
        malicious_description=f"Detection rate of {detections}/{engines_count}",
    )

    # Create Domain indicator
    domain_indicator = Common.Domain(
        domain=domain, dbot_score=dbot_score, detection_engines=engines_count, positive_detections=detections
    )

    # Build custom context outputs
    outputs = None if reputation_only else response

    readable_data = {"Name": domain, "DNS": domain, "DetectionEngines": engines_count, "PositiveDetections": detections}

    readable_output = tableToMarkdown(f"APIVoid information for {domain}:", readable_data)

    return CommandResults(
        outputs_prefix="APIVoid.Domain",
        outputs_key_field="host",
        outputs=outputs,
        indicator=domain_indicator,
        readable_output=readable_output,
        raw_response=response,
    )


def url_reputation_command(
    client: Client, args: dict, reputation_only: bool, thresholds: dict, reliability: str
) -> CommandResults:
    """
    Get URL reputation from APIVoid V2 API

    Args:
        client: APIVoid client instance
        args: Command arguments
        reputation_only: If True, return only standard URL context
        thresholds: Dict with 'good', 'suspicious', 'bad' thresholds
        reliability: Source reliability level

    Returns:
        CommandResults object
    """
    url = args.get("url")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["url_reputation"], {"url": url})
    except Exception as e:
        raise DemistoException(f"Failed to get URL reputation: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error checking URL {url}: {response.get("error")}')

    # Add url to response for context
    response["url"] = url

    # Apply field mapping recursively to entire response
    response = map_fields(response, exclude_mappings=["name"])

    # Extract data
    domain_blacklist = response.get("domain_blacklist", {})
    engines_count = domain_blacklist.get("engines_count", 0)
    detections = domain_blacklist.get("detections", 0)
    for key in ["ns", "mx"]:
        dns_records_inner_data = demisto.get(response, f"dns_records.{key}", {})
        if dns_records_inner_data:
            response["dns_records"][key] = {"records": dns_records_inner_data}  # Backward Competability

    # Calculate DBot score
    score = calculate_dbot_score(engines_count, detections, thresholds)

    # Create DBot score object
    dbot_score = Common.DBotScore(
        indicator=url,
        indicator_type=DBotScoreType.URL,
        integration_name="APIVoid",
        score=score,
        reliability=reliability,
        malicious_description=f"Detection rate of {detections}/{engines_count}",
    )

    # Create URL indicator
    url_indicator = Common.URL(url=url, dbot_score=dbot_score, detection_engines=engines_count, positive_detections=detections)

    # Build custom context outputs
    outputs = None if reputation_only else response

    readable_data = {"Data": url, "DetectionEngines": engines_count, "PositiveDetections": detections}

    readable_output = tableToMarkdown(f"APIVoid information for {url}:", readable_data)

    return CommandResults(
        outputs_prefix="APIVoid.URL",
        outputs_key_field="url",
        outputs=outputs,
        indicator=url_indicator,
        readable_output=readable_output,
        raw_response=response,
    )


def dns_lookup_command(client: Client, args: dict) -> CommandResults:
    """
    Get DNS records for a host

    Args:
        client: APIVoid client instance
        args: Command arguments

    Returns:
        CommandResults object
    """
    host = args.get("host")
    dns_type = args.get("type", "A")  # Required parameter with default

    request_data = {"host": host, "dns_types": dns_type}

    try:
        response = client.api_request(ENDPOINTS["dns_lookup"], request_data)
    except Exception as e:
        raise DemistoException(f"Failed to get DNS records: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error looking up DNS for {host}: {response.get("error")}')

    response = map_fields(response)

    records = response.get("records", {})

    if records:
        # Build outputs with host and type
        outputs = {
            "host": host,
            "type": dns_type,
        }

        # Build readable output - check for the requested type in lowercase
        dns_type_lower = dns_type.lower()

        # Check if the requested type exists in records
        if dns_type_lower in records and records[dns_type_lower]:
            type_records = records[dns_type_lower]
            outputs["items"] = type_records
            md = tableToMarkdown(f"APIVoid DNS {dns_type.upper()} records for {host}:", type_records)
        else:
            md = f"## No {dns_type.upper()} records found for {host}"

        return CommandResults(
            outputs_prefix="APIVoid.DNS", outputs_key_field="host", outputs=outputs, readable_output=md, raw_response=response
        )
    else:
        return CommandResults(readable_output=f"## No DNS records found for {host}", raw_response=response)


def ssl_info_command(client: Client, args: dict) -> CommandResults:
    """
    Get SSL certificate information for a host

    Args:
        client: APIVoid client instance
        args: Command arguments

    Returns:
        CommandResults object
    """
    host = args.get("host")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["ssl_info"], {"host": host})
    except Exception as e:
        raise DemistoException(f"Failed to get SSL info: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error getting SSL info for {host}: {response.get("error")}')

    response = map_fields(response, exclude_mappings=["name"])

    certificate = response.get("certificate", {})
    if certificate:
        md_data = dict(certificate)
        if "details" in md_data:
            del md_data["details"]

        certificate["host"] = host
        md = tableToMarkdown(f"APIVoid SSL Information for {host}:", md_data)
    else:
        md = f"## No SSL information for {host}"
    outputs = certificate if certificate else None

    return CommandResults(
        outputs_prefix="APIVoid.SSL", outputs_key_field="host", outputs=outputs, readable_output=md, raw_response=response
    )


def email_verify_command(client: Client, args: dict) -> CommandResults:
    """
    Verify an email address

    Args:
        client: APIVoid client instance
        args: Command arguments

    Returns:
        CommandResults object
    """
    email = args.get("email")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["email_verify"], {"email": email})
    except Exception as e:
        raise DemistoException(f"Failed to verify email: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error verifying email {email}: {response.get("error")}')

    if response:
        # Create simple table
        md = tableToMarkdown(f"APIVoid Email Information for {email}:", response)
    else:
        md = f"## No information for {email}"

    return CommandResults(
        outputs_prefix="APIVoid.Email", outputs_key_field="email", outputs=response, readable_output=md, raw_response=response
    )


def parked_domain_command(client: Client, args: dict) -> CommandResults:
    """
    Check if a domain is parked

    Args:
        client: APIVoid client instance
        args: Command arguments

    Returns:
        CommandResults object
    """
    domain = args.get("domain")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["parked_domain"], {"host": domain})
    except Exception as e:
        raise DemistoException(f"Failed to check parked domain: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error checking parked domain {domain}: {response.get("error")}')

    if response:
        ec = {"APIVoid.ParkedDomain(val.host && val.host == obj.host)": response, "Domain": {"Name": domain}}
        md = tableToMarkdown(f"APIVoid Parked Domain Information for {domain}:", response)
    else:
        ec = {}
        md = f"## No information for {domain}"

    return CommandResults(outputs=ec, readable_output=md, raw_response=response)


def domain_age_command(client: Client, args: dict) -> CommandResults:
    """
    Get domain age information

    Args:
        client: APIVoid client instance
        args: Command arguments

    Returns:
        CommandResults object
    """
    domain = args.get("domain")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["domain_age"], {"host": domain})
    except Exception as e:
        raise DemistoException(f"Failed to get domain age: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error getting domain age for {domain}: {response.get("error")}')

    if response:
        ec = {
            "APIVoid.DomainAge(val.host && val.host == obj.host)": response,
            "Domain": {"Name": domain, "CreationDate": response.get("domain_creation_date")},
        }
        md = tableToMarkdown(f"APIVoid Domain Age Information for {domain}:", response)
    else:
        ec = {}
        md = f"## No information for {domain}"

    return CommandResults(outputs=ec, readable_output=md, raw_response=response)


def screenshot_command(client: Client, args: dict) -> dict:
    """
    Capture a screenshot of a URL

    Args:
        client: APIVoid client instance
        args: Command arguments

    Returns:
        File result dict
    """
    url = args.get("url", "")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["screenshot"], {"url": url})
    except Exception as e:
        raise DemistoException(f"Failed to capture screenshot: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error capturing screenshot for {url}: {response.get("error")}')

    data = demisto.get(response, "rendered_file.base64_file")
    if data:
        # Create file name
        file_name = url.replace("https", "").replace("http", "").replace("://", "").replace(".", "_")
        file_name += "_capture.png"
        return fileResult(file_name, b64decode(data))
    else:
        raise DemistoException(f"No screenshot data returned for {url}")


def url_to_pdf_command(client: Client, args: dict) -> dict:
    """
    Convert a URL to PDF

    Args:
        client: APIVoid client instance
        args: Command arguments

    Returns:
        File result dict
    """
    url = args.get("url", "")
    demisto.debug(f"APIVoid: url_to_pdf_command called with url={url}")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["url_to_pdf"], {"url": url})
    except Exception as e:
        raise DemistoException(f"Failed to convert URL to PDF: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error converting URL to PDF for {url}: {response.get("error")}')

    data = demisto.get(response, "rendered_file.base64_file")
    if data:
        # Create file name
        file_name = url.replace("https", "").replace("http", "").replace("://", "").replace(".", "_")
        file_name += "_capture.pdf"
        return fileResult(file_name, b64decode(data))
    else:
        raise DemistoException(f"No PDF data returned for {url}")


def site_trustworthiness_command(client: Client, args: dict) -> CommandResults:
    """
    Get site trustworthiness information

    Args:
        client: APIVoid client instance
        args: Command arguments

    Returns:
        CommandResults object
    """
    host = args.get("host")
    demisto.debug(f"APIVoid: site_trustworthiness_command called with host={host}")

    # Make API request
    try:
        response = client.api_request(ENDPOINTS["site_trustworthiness"], {"host": host})
    except Exception as e:
        raise DemistoException(f"Failed to get site trustworthiness: {str(e)}")

    # Handle API errors
    if "error" in response:
        raise DemistoException(f'Error getting site trustworthiness for {host}: {response.get("error")}')

    response = map_fields(response, exclude_mappings=["name"])

    # Build outputs - following YML structure
    outputs = {}
    if response:
        response["host"] = host

        # Map security_checks domain age fields to domain_age structure for YML compatibility
        # The YML expects APIVoid.SiteTrust.domain_age.* fields
        security_checks = response.get("security_checks", {})
        if security_checks:
            # Create domain_age object from security_checks fields
            domain_age = {}
            if "domain_creation_date" in security_checks:
                domain_age["domain_creation_date"] = security_checks.get("domain_creation_date")
                domain_age["found"] = True
            if "domain_age_in_days" in security_checks:
                domain_age["domain_age_in_days"] = security_checks.get("domain_age_in_days")
            if "domain_age_in_months" in security_checks:
                domain_age["domain_age_in_months"] = security_checks.get("domain_age_in_months")
            if "domain_age_in_years" in security_checks:
                domain_age["domain_age_in_years"] = security_checks.get("domain_age_in_years")

            if domain_age:
                response["domain_age"] = domain_age

        outputs = response

        # Create simple table
        md = tableToMarkdown(f"APIVoid Site Trustworthiness for {host}:", response)
    else:
        md = f"## No information for {host}"

    return CommandResults(
        outputs_prefix="APIVoid.SiteTrust", outputs_key_field="host", outputs=outputs, readable_output=md, raw_response=response
    )


def test_module(client: Client) -> str:
    """
    Test the integration by making a simple API call

    Args:
        client: APIVoid client instance

    Returns:
        'ok' if successful, error message otherwise
    """
    try:
        # Use IP reputation endpoint with a known IP for testing
        response = client.api_request(ENDPOINTS["ip_reputation"], {"ip": "8.8.8.8"})
        if "error" in response:
            return f'Test Failed: {response.get("error")}'
        return "ok"
    except Exception as e:
        return f"Test Failed: {str(e)}"


def main():
    """Main execution function"""

    # Get parameters once
    params = demisto.params()
    base_url = params.get("url", "https://api.apivoid.com")
    apikey = params.get("credentials", {}).get("password") or params.get("apikey", "")
    verify = not params.get("insecure", False)
    proxy = params.get("proxy", False)
    reliability = params.get("integrationReliability", "C - Fairly reliable")

    # Threshold configuration
    thresholds = {
        "suspicious": arg_to_number(params.get("suspicious", 30)),
        "bad": arg_to_number(params.get("bad", 60)),
    }

    demisto.debug(f"APIVoid: Initialized with base_url={base_url}, verify={verify}, proxy={proxy}, reliability={reliability}")
    demisto.debug(f'APIVoid: Thresholds configured - ' f'suspicious={thresholds["suspicious"]}%, bad={thresholds["bad"]}%')

    # Create client
    client = Client(base_url, apikey, verify, proxy)

    # Get command and args
    command = demisto.command()
    args = demisto.args()

    demisto.debug(f"APIVoid: Command being called is {command}")

    try:
        result: None | str | CommandResults | dict[str, Any] = None
        # Command routing
        if command == "test-module":
            result = test_module(client)
            return_results(result)

        elif command in ["ip", "apivoid-ip"]:
            reputation_only = command == "ip"
            result = ip_reputation_command(client, args, reputation_only, thresholds, reliability)
            return_results(result)

        elif command in ["domain", "apivoid-domain"]:
            reputation_only = command == "domain"
            result = domain_reputation_command(client, args, reputation_only, thresholds, reliability)
            return_results(result)

        elif command in ["url", "apivoid-url"]:
            reputation_only = command == "url"
            result = url_reputation_command(client, args, reputation_only, thresholds, reliability)
            return_results(result)

        elif command == "apivoid-dns-lookup":
            result = dns_lookup_command(client, args)
            return_results(result)

        elif command == "apivoid-ssl-info":
            result = ssl_info_command(client, args)
            return_results(result)

        elif command == "apivoid-email-verify":
            result = email_verify_command(client, args)
            return_results(result)

        elif command == "apivoid-parked-domain":
            result = parked_domain_command(client, args)
            return_results(result)

        elif command == "apivoid-domain-age":
            result = domain_age_command(client, args)
            return_results(result)

        elif command == "apivoid-url-to-image":
            result = screenshot_command(client, args)
            return_results(result)

        elif command == "apivoid-url-to-pdf":
            result = url_to_pdf_command(client, args)
            return_results(result)

        elif command == "apivoid-site-trustworthiness":
            result = site_trustworthiness_command(client, args)
            return_results(result)

        elif command in ["apivoid-threatlog", "apivoid-url-to-html"]:
            raise DemistoException(f"Command {command} is not supported in API V2")
        else:
            raise NotImplementedError(f"Command {command} is not implemented")

    except Exception as e:
        return_error(f"Failed to execute {command} command. Error: {str(e)}")


if __name__ in ("__main__", "__builtin__", "builtins"):
    main()