APIs
Malanta API
Threats, Exposures & Prevented · IoPA Cluster · Gold Query (Enrichment) · STIX/TAXII Feed
Version 2.0 | July 2026
Contents
- Overview
- Authentication
- Platform API
- IoPA Cluster API
- Gold Query API
- Conventions
- Domains
- GET /v1/domains/{domain}/reputation
- POST /v1/domains/reputation
- GET /v1/domains/{domain}/whois
- POST /v1/domains/whois
- GET /v1/domains/{domain}/certificates
- POST /v1/domains/certificates
- GET /v1/domains/{domain}/co-hosted-domains
- POST /v1/domains/co-hosted-domains
- GET /v1/domains/{domain}/ip-ranges
- POST /v1/domains/ip-ranges
- GET /v1/domains/{domain}/dns-records
- POST /v1/domains/dns-records
- GET /v1/domains/{domain}/info
- GET /v1/domains/{domain}/code-repos
- FQDNs
- IPs
- Clusters
- Code Repos
- Certificates
- STIX/TAXII Feed API
- Quick reference
Overview
The Malanta API gives you programmatic access to pre-attack intelligence, exposure data, and threat enrichment for your monitored organizations and scopes.
There are four API families:
- Platform API — Retrieve imminent threats, exposures, and prevented items for your organization and scopes.
- IoPA Cluster API — Submit an indicator for pre-attack cluster analysis and retrieve the results.
- Gold Query API — Look up reputation and enrichment for any domain, host, IP, cluster, or certificate (WHOIS, certificates, co-hosted domains, hosting/ASN, DNS records, and more).
- STIX/TAXII Feed API — Retrieve attack-infrastructure clusters in STIX 2.1 format over the TAXII 2.1 protocol.
Base URLs
API family | Base URL |
|---|---|
Platform API (Threats, Exposures, Prevented) | |
IoPA Cluster API | |
Gold Query API | |
STIX/TAXII Feed API |
Authentication
All requests require your Malanta API key. Keys are prefixed with malanta_. A missing or invalid key is rejected before the request reaches the service (401/403).
Most endpoints use the x-api-key header:
x-api-key: malanta_xxxxxxxxxxxxxThe STIX/TAXII Feed API is the only exception — it uses Bearer token authentication:
Authorization: Bearer malanta_xxxxxxxxxxxxxKeep your API key private. Never expose it in frontend code, mobile apps, or public repositories.
Platform API
The Platform API returns operational threats, exposures, and prevented items for a specific organization and scope. All three endpoints are paginated and share the same item structure.
Threats
Returns a paginated list of imminent pre-attack threats.
Endpoint: GET /v1/organizations/{organization_id}/scopes/{scope_id}/threats/page
Path parameters
organization_id— your organization identifierscope_id— the monitored scope identifier
Query parameters
PageSize— items per page (e.g. 30)PageNumber— page number (1-indexed)
Example request
curl --request GET \
--url 'https://app.malanta.ai/api/v1/organizations/{organization_id}/scopes/{scope_id}/threats/page?PageSize=30&PageNumber=1' \
--header 'Accept: application/json' \
--header 'x-api-key: malanta_xxxxxxxxxxxxx'Example response
{
"data": [
{
"exposure_id": "855eb38b-a9e0-402f-8cd6-186ee0b81481",
"root_domain": "acme.com",
"exposed_asset_name": "https://short.url/acme_com impersonates acme.com using a short URL service, redirecting to a malicious site and possibly used for malware delivery or phishing.",
"exposed_asset_type": "Registered domain",
"exposed_asset_identifier": "acme.com",
"exposed_asset_status_timeline": [
{ "timestamp": 1767537152, "status": "Impersonated" }
],
"exposure_type": "Malicious Domain",
"exposure_scenario_category": "Domain Infrastructure Abuse",
"exposure_scenario": "Short Url",
"exposure_root_cause_name": "Short URL domain registration",
"exposure_root_cause_identifier": "https://short.url/acme_com",
"business_impact": {
"impact_category": "Reputation Damage",
"impact_summary": "..."
},
"attack_analysis": "...",
"attack_infrastructure": {
"clusters_ids": ["0474355E-6816-178C-4335-6556B264623F"],
"status": "completed"
},
"exposure_attack_indicators": ["192.0.2.100"]
}
],
"total_count": 46,
"page_size": 30,
"page_number": 1,
"has_next": true,
"has_previous": false,
"next_page": 2,
"previous_page": null
}Response fields
data— array of itemstotal_count— total number of itemspage_size/page_number— current pagination statehas_next/has_previous— whether more pages existnext_page/previous_page— adjacent page numbers (ornull)
Item fields
exposure_id— unique identifierroot_domain— the primary organizational domain being targetedexposed_asset_name— description of the exposed assetexposed_asset_type— Registered domain, Subdomain, or IP Addressexposed_asset_identifier— the specific assetexposed_asset_status_timeline— status changes with timestampsexposure_type— classification (e.g. Malicious Domain)exposure_scenario_category/exposure_scenario— category and specific scenarioexposure_root_cause_name/exposure_root_cause_identifier— root causebusiness_impact— impact category and summaryattack_analysis— threat analysis narrativeattack_infrastructure— associated cluster IDs and statusexposure_attack_indicators— related indicators (IPs, domains)
Use attack_infrastructure.clusters_ids to pivot from a threat into the related pre-attack infrastructure clusters for deeper investigation.
Exposures
Returns a paginated list of exposed assets for an organization and scope.
Endpoint: GET /v1/organizations/{organization_id}/scopes/{scope_id}/exposures/page
Path parameters, query parameters, response shape, and item fields are identical to the Threats endpoint.
Example request
curl --request GET \
--url 'https://app.malanta.ai/api/v1/organizations/{organization_id}/scopes/{scope_id}/exposures/page?PageSize=30&PageNumber=1' \
--header 'Accept: application/json' \
--header 'x-api-key: malanta_xxxxxxxxxxxxx'Prevented
Returns a paginated list of threats and exposures that have been prevented or remediated. Same pagination and item structure as Threats and Exposures.
Endpoint: GET /v1/organizations/{organization_id}/scopes/{scope_id}/prevented/page
To retrieve only the total count without the full list:
Endpoint: GET /v1/organizations/{organization_id}/scopes/{scope_id}/prevented/count
IoPA Cluster API
Submit an indicator (domain, IP, or email address) for pre-attack cluster analysis, then poll for the results. This is a two-step asynchronous flow.
Step 1 — Submit an indicator
Endpoint: POST /v1/clusters/scan_iopa
Request body
{ "indicator": "example.it" }indicator— a domain, IP address, or email address to analyze
curl --request POST \
--url 'https://app.malanta.ai/api/v1/clusters/scan_iopa' \
--header 'Content-Type: application/json' \
--header 'x-api-key: malanta_xxxxxxxxxxxxx' \
--data '{ "indicator": "example.it" }'Step 2 — Poll for results
Endpoint: GET /v1/clusters/iopa/?indicator={indicator}
indicator— the indicator submitted in Step 1 (URL-encoded)
curl --request GET \
--url 'https://app.malanta.ai/api/v1/clusters/iopa/?indicator=example.it' \
--header 'x-api-key: malanta_xxxxxxxxxxxxx'Example response
{
"clusters": [
{
"cluster_id": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
"presigned_url": "https://s3.amazonaws.com/..."
}
],
"raw_data": { "nodes": [], "relations": [] },
"version": "1.0",
"status": "completed"
}Response fields
clusters— array of clusters, each with acluster_idand apresigned_urlraw_data— graph data withnodesandrelationsstatus—in_progressorcompleted
While status is in_progress, poll the GET endpoint every 10 seconds until it becomes completed.
Downloading cluster data. Download the full cluster data using the presigned_url from each cluster. These are pre-signed links that require no additional authentication.
curl --request GET --url '{presigned_url}'Gold Query API
A read-only enrichment API for domains, hosts, IPs, clusters, and certificates: reputation, WHOIS, certificates, co-hosted domains, hosting/ASN info, DNS records, and cluster membership. All endpoints use the base URL https://app.malanta.ai/data and follow the conventions below.
Reputation note: a verdict of MALICIOUS means the entity is flagged; UNKNOWN means "not flagged" — it is never a claim that an entity is benign.
Conventions
The Gold Query API uses a single, consistent response format across every endpoint.
Response envelope
Every response is shaped as { data, query, meta, pagination }:
data— the payload (an object, an array, ornullwhen there is no match).query.indicator— echoes the entity you queried (nullon batch requests).meta— request metadata:endpoint,generated_at, and, on time-aware endpoints, acoveragewindow (first_observed_at/last_observed_at).pagination— always present; meaningful only on paginated collections.
{
"data": { "...": "endpoint-specific payload" },
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": {
"endpoint": "/v1/domains/{domain}/reputation",
"generated_at": "2026-06-24T10:53:59.016Z",
"coverage": { "first_observed_at": "2023-06-24T00:00:00Z", "last_observed_at": "2026-05-18T00:00:00Z" }
},
"pagination": { "has_more": false, "next_cursor": null }
}Indicator object
A reference to an entity, used both in query.indicator and inside payloads.
Field | Type | Notes |
|---|---|---|
| string | one of |
| string | the normalized domain or IP |
Single lookups vs. batch
- GET — single-entity lookups (one domain, host, IP, cluster, or certificate).
- POST — batch lookups. Send a JSON body with 1–100 entities. Requests with a body must set
Content-Type: application/json.
When resolving more than one entity, prefer the batch POST route. Batch responses return one entry per input, each with its own indicator (the top-level query.indicator is null).
Temporal parameters
Time-aware endpoints (WHOIS, certificates, co-hosted domains, DNS records, IP info, IP domains) accept:
Param | Type | Default | Meaning |
|---|---|---|---|
| ISO-8601 | none | lower bound of the observation window |
| ISO-8601 | none | upper bound (exclusive) |
| boolean |
| return the full timeline instead of the current view |
With no temporal parameters you get the current/latest view. Batch (POST) routes are current-only. Passing since later than until returns 400.
Pagination
Collection endpoints are cursor-paged:
Param | Type | Default | Notes |
|---|---|---|---|
| integer | 100 | page size, 1–1000 |
| string | none | pass back |
When more rows exist, pagination.has_more is true and pagination.next_cursor holds the token for the next page. To retrieve a full collection, loop while has_more is true, passing next_cursor as ?cursor=.
Domain vs. host scope
/v1/domains/{domain}/*routes are registered-domain scoped:{domain}must be a registrable domain such asexample.comorexample.co.uk. A subdomain (e.g.www.example.com) returns422./v1/fqdns/{fqdn}/*routes accept any host (apex or subdomain) and return data for that exact host only.
Use /v1/domains when you know the input is a registrable domain — it validates that for you and exposes more resources (reputation, WHOIS, co-hosted domains). Use /v1/fqdns for a specific host, or when you don't know in advance whether a hostname is an apex or a subdomain.
Errors
Error responses are shaped { "detail": "...", "request_id": "..." }.
Status | When |
|---|---|
| invalid parameter (e.g. |
| missing or invalid API key |
| malformed domain/IP, or a subdomain sent to a registered-domain route |
| internal error |
| service temporarily unavailable |
| upstream query timed out |
data: null (or an empty array) means "no data", not an error — only a non-2xx status is an error.
Domains
Registered-domain-scoped lookups ({domain} must be a registrable domain).
GET /v1/domains/{domain}/reputation
Malanta's verdict for a registered domain: verdict and signal labels, a 0–1 malicious_score (with a HIGH/MEDIUM/LOW band), attributed apt_names, ioc_sources, context, and the clusters the domain belongs to.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | registered domain; a subdomain returns |
Enums: verdict = MALICIOUS | UNKNOWN; labels[] = IOPA | IOC; band = HIGH | MEDIUM | LOW.
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/reputation" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"reputation": { "verdict": "MALICIOUS", "labels": ["IOPA", "IOC"], "malicious_score": 0.98, "malicious_score_band": "HIGH" },
"apt_names": [],
"ioc_sources": ["malanta", "blackweb"],
"context": ["RedLine Stealer botnet C2 server"],
"clusters": [
{ "cluster_id": "33b3f438-1a2b-4c3d-9e4f-5a6b7c8d9e0f", "member_count": 30, "joined_at": "2026-05-20T00:00:00Z", "reputation": { "malicious_score": 1.0, "malicious_score_band": "HIGH" } }
],
"timestamps": { "first_observed_at": "2025-10-20T15:48:32.208Z", "last_classified_at": "2026-06-22T07:00:45.774Z", "last_observed_at": "2026-06-22T09:34:57.004Z" }
},
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": { "endpoint": "/v1/domains/{domain}/reputation", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}For an UNKNOWN verdict, malicious_score is null and apt_names / ioc_sources / context / clusters are empty.
POST /v1/domains/reputation
Batch reputation for 1–100 registered domains. Returns one entry per input, each with its own indicator.
Body field | Type | Notes |
|---|---|---|
| array<string> | 1–100 registered domains |
curl -X POST "https://app.malanta.ai/data/v1/domains/reputation" \
-H "x-api-key: malanta_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"domains": ["example.com", "example.org"]}'GET /v1/domains/{domain}/whois
The current WHOIS registration record. With a temporal parameter, an inline history[] of prior versions (newest first) is added. data is null if the domain has no registration record.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | registered domain |
| query | temporal | add the prior-version |
Contact roles: REGISTRANT, ADMINISTRATIVE, TECHNICAL, BILLING.
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/whois" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"observed_at": "2026-05-18T01:40:59Z",
"created_at": "2022-11-06T00:00:00Z",
"updated_at": "2026-05-10T00:00:00Z",
"expires_at": "2026-11-06T00:00:00Z",
"registrar": { "id": "1479", "name": "Example Registrar, LLC", "whois_server": "whois.example-registrar.com", "url": "http://www.example-registrar.com" },
"statuses": ["clientTransferProhibited"],
"name_servers": ["ns1.example-dns.com", "ns2.example-dns.com"],
"contacts": [
{ "role": "REGISTRANT", "name": "Privacy Service", "organization": "Example Privacy", "address": { "street": null, "city": "Phoenix", "state": "AZ", "postal_code": null, "country": "United States" }, "email": "abc@privacy.example", "email_local_part": "abc", "email_domain": "privacy.example", "phone": null, "fax": null }
]
},
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": { "endpoint": "/v1/domains/{domain}/whois", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/domains/whois
Batch WHOIS for 1–100 registered domains. Each entry is { indicator, whois }, where whois is the full record or null when the domain has no registration record.
GET /v1/domains/{domain}/certificates
Certificates linked to the exact domain. By default returns currently-valid certificates; history / since / until include expired and superseded certificates. Cursor-paged.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | registered domain |
| query | temporal | include expired/older certificates |
| query | paging | see Pagination |
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/certificates?limit=50" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{
"certificate_id": "94273995-fdaa-4b24-a1fd-e052e3520736",
"serial_number": "120022056273139920459243120498800462479",
"serial_hex": "6563e1df3819f6ecf349f25a7ddda3c54ea",
"validity": { "not_before_at": "2026-06-11T22:22:58Z", "not_after_at": "2026-09-09T22:22:57Z" },
"subject": { "common_name": "webdisk.example.com", "alternative_names": ["example.com", "mail.example.com", "www.example.com"] },
"issuer": { "common_name": "YR1", "organization": "Let's Encrypt", "country": "US", "locality": null },
"is_self_signed": false,
"fingerprints": { "sha1": "90808e86a0d9…", "sha256": "b868eaa376c6d6b612c0fda6cabf6805e0d5e57e5a3201130ccfafc4e1afb81c" },
"period": { "first_observed_at": "2026-06-12T00:00:00Z", "last_observed_at": "2026-06-14T08:42:39Z" }
}
],
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": { "endpoint": "/v1/domains/{domain}/certificates", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": true, "next_cursor": "eyJvIjoiMjAyNi0wNi0xMSIsImMiOiI1ZDliMWU3YSJ9" }
}POST /v1/domains/certificates
Batch certificates for 1–100 registered domains, grouped per input: { indicator, certificates: [...] }.
GET /v1/domains/{domain}/co-hosted-domains
Domains that share an IP with the queried domain, each with the linking via_ip and observation dates. Current associations by default; history / since / until widen to the full timeline. Cursor-paged.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | registered domain |
| query | temporal | widen to historical associations |
| query | paging | see Pagination |
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/co-hosted-domains" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{ "co_hosted_domain": { "type": "domain-name", "value": "co-tenant-a.example" }, "via_ip": { "type": "ipv4-addr", "value": "119.82.9.133" }, "first_observed_at": "2026-02-04T00:00:00Z", "last_observed_at": "2026-06-01T00:00:00Z" },
{ "co_hosted_domain": { "type": "fqdn", "value": "mail.co-tenant-b.example" }, "via_ip": { "type": "ipv4-addr", "value": "119.82.9.133" }, "first_observed_at": "2026-03-01T00:00:00Z", "last_observed_at": "2026-06-01T00:00:00Z" }
],
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": { "endpoint": "/v1/domains/{domain}/co-hosted-domains", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/domains/co-hosted-domains
Batch co-hosted domains for 1–100 registered domains, grouped per input.
GET /v1/domains/{domain}/ip-ranges
The IPs the domain is currently hosted on — one item per IP — each with its observed window and the network block it belongs to (start/end IP, CIDR, company, ASN, geo, type). Current-only. Cursor-paged.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | registered domain |
| query | paging | see Pagination |
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/ip-ranges" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{
"ip": { "type": "ipv4-addr", "value": "13.226.34.51" },
"first_observed_at": "2026-02-04T00:00:00Z",
"last_observed_at": "2026-06-28T00:00:00Z",
"ip_range": { "start_ip": "13.226.0.0", "end_ip": "13.226.255.255", "cidr": "13.226.0.0/16" },
"company": { "name": "Amazon.com, Inc.", "domain": "amazon.com" },
"asn": { "number": 16509, "org": "Amazon.com, Inc.", "domain": "amazon.com" },
"ip_type": "HOSTING",
"geo": { "country": "US" }
}
],
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": { "endpoint": "/v1/domains/{domain}/ip-ranges", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/domains/ip-ranges
Batch for 1–100 registered domains, grouped per input: { indicator, ips: [...] }.
GET /v1/domains/{domain}/dns-records
Distinct DNS records observed for the exact domain — a flat array, one item per distinct (record_type, value). Default returns each record type's latest resolution; history / since / until widen to the full timeline.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | registered domain |
| query | string |
|
| query | temporal | include superseded records |
| query | paging | see Pagination |
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/dns-records" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{ "record_type": "A", "value": "203.0.113.10", "target": { "type": "ipv4-addr", "value": "203.0.113.10" }, "ttl": null, "period": { "first_observed_at": "2026-01-05T00:00:00Z", "last_observed_at": "2026-06-28T00:00:00Z" } }
],
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": { "endpoint": "/v1/domains/{domain}/dns-records", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/domains/dns-records
Batch DNS records for 1–100 registered domains, grouped per input: { indicator, dns_records: [...] }.
GET /v1/domains/{domain}/info
A bounded overview of everything known about a domain. summary inlines a reputation headline (verdict + score); available is a set of existence flags telling you which other endpoints have data for this domain (whois, certificates, clusters, dns_records, co_hosted_domains, ipinfo, code_repos).
Param | In | Type | Notes |
|---|---|---|---|
| path | string | registered domain; a subdomain returns |
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/info" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"summary": { "reputation": { "verdict": "MALICIOUS", "malicious_score": 0.92, "malicious_score_band": "HIGH" } },
"available": { "whois": true, "certificates": true, "clusters": true, "dns_records": true, "co_hosted_domains": false, "ipinfo": true, "code_repos": true },
"first_observed_at": "2023-06-24T00:00:00Z",
"last_observed_at": "2026-05-18T00:00:00Z"
},
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": { "endpoint": "/v1/domains/{domain}/info", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}GET /v1/domains/{domain}/code-repos
Public source-code repositories in which the domain appears, grouped by repository — with the file/line hits in evidence[], how the match was found (occurrence), and repository metadata (URL, stars, language). This is an exposure/attribution signal, not a verdict: a legitimate domain can appear in flagged repositories.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | registered domain; a subdomain returns |
| query | ISO-8601 | window on when the match was discovered |
| query | boolean | default |
| query | paging | see Pagination |
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/code-repos" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{
"repo": { "repo_id": "example-org/example-repo@master", "url": "https://github.com/example-org/example-repo", "platform": "github", "host": "github.com", "owner": "example-org", "stars": 1288, "forks": 143, "primary_language": "Python", "indicator_count": 12, "discovered_at": "2026-02-19T08:11:24.360Z", "last_observed_at": "2026-02-19T08:11:24.360Z" },
"occurrence": { "seen_in": { "feed": true, "pivot": false }, "source_type": "feed", "feed_name": "urlhaus", "validation_status": "valid", "discovered_at": "2026-02-19T08:11:24.360Z" },
"pivot": { "depth": 0, "method": null, "actor": null, "confidence": 1.0 },
"evidence": [
{ "file": "config/hosts.txt", "line": 42, "snippet": "example.com" }
]
}
],
"query": { "indicator": { "type": "domain-name", "value": "example.com" } },
"meta": { "endpoint": "/v1/domains/{domain}/code-repos", "generated_at": "2026-07-05T10:53:59.016Z" },
"pagination": { "has_more": true, "next_cursor": "…" }
}FQDNs
Host-scoped endpoints. {fqdn} is an exact host (apex or subdomain, e.g. www.example.com).
GET /v1/fqdns/{fqdn}/certificates
Certificates linked to the exact host. Same shape and temporal/pagination behavior as the domain certificates endpoint. The queried host is echoed at query.indicator with type: "fqdn".
Param | In | Type | Notes |
|---|---|---|---|
| path | string | any well-formed host (apex or subdomain) |
| query | temporal | include expired/older certificates |
| query | paging | see Pagination |
curl -X GET "https://app.malanta.ai/data/v1/fqdns/www.example.com/certificates" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{
"certificate_id": "94273995-fdaa-4b24-a1fd-e052e3520736",
"serial_number": "120022056273139920459243120498800462479",
"serial_hex": "6563e1df3819f6ecf349f25a7ddda3c54ea",
"validity": { "not_before_at": "2026-06-11T22:22:58Z", "not_after_at": "2026-09-09T22:22:57Z" },
"subject": { "common_name": "www.example.com", "alternative_names": ["www.example.com"] },
"issuer": { "common_name": "YR1", "organization": "Let's Encrypt", "country": "US", "locality": null },
"is_self_signed": false,
"fingerprints": { "sha1": "90808e86a0d9…", "sha256": "b868eaa376c6d6b612c0fda6cabf6805e0d5e57e5a3201130ccfafc4e1afb81c" },
"period": { "first_observed_at": "2026-06-12T00:00:00Z", "last_observed_at": "2026-06-14T08:42:39Z" }
}
],
"query": { "indicator": { "type": "fqdn", "value": "www.example.com" } },
"meta": { "endpoint": "/v1/fqdns/{fqdn}/certificates", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/fqdns/certificates
Batch certificates for 1–100 hosts, grouped per input: { indicator, certificates: [...] }.
curl -X POST "https://app.malanta.ai/data/v1/fqdns/certificates" \
-H "x-api-key: malanta_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"fqdns": ["www.example.com", "mail.example.com"]}'GET /v1/fqdns/{fqdn}/dns-records
Distinct DNS records observed for the exact host — a flat array, one item per distinct (record_type, value). Default returns each record type's latest resolution; history / since / until return the full timeline. target is a typed indicator (an IP for an A/AAAA record, a domain/host for a CNAME).
Param | In | Type | Notes |
|---|---|---|---|
| path | string | any well-formed host (apex or subdomain) |
| query | string |
|
| query | temporal | include superseded records |
| query | paging | see Pagination |
curl -X GET "https://app.malanta.ai/data/v1/fqdns/www.example.com/dns-records" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{ "record_type": "A", "value": "203.0.113.10", "target": { "type": "ipv4-addr", "value": "203.0.113.10" }, "ttl": null, "period": { "first_observed_at": "2026-01-05T00:00:00Z", "last_observed_at": "2026-06-28T00:00:00Z" } },
{ "record_type": "CNAME", "value": "proxy-ssl.webflow.com", "target": { "type": "fqdn", "value": "proxy-ssl.webflow.com" }, "ttl": null, "period": { "first_observed_at": "2025-07-12T06:30:36.822Z", "last_observed_at": "2026-06-28T00:00:00Z" } }
],
"query": { "indicator": { "type": "fqdn", "value": "www.example.com" } },
"meta": { "endpoint": "/v1/fqdns/{fqdn}/dns-records", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/fqdns/dns-records
Batch DNS records for 1–100 hosts, grouped per input: { indicator, dns_records: [...] }.
curl -X POST "https://app.malanta.ai/data/v1/fqdns/dns-records" \
-H "x-api-key: malanta_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"fqdns": ["www.example.com", "mail.example.com"]}'GET /v1/fqdns/{fqdn}/code-repos
Public source-code repositories an exact host appears in — same object and behavior as the domain code-repos endpoint, scoped to the host.
curl -X GET "https://app.malanta.ai/data/v1/fqdns/www.example.com/code-repos" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{
"repo": { "repo_id": "example-org/example-repo@master", "url": "https://github.com/example-org/example-repo", "platform": "github", "host": "github.com", "owner": "example-org", "stars": 1288, "forks": 143, "primary_language": "Python", "indicator_count": 5, "discovered_at": "2026-02-19T08:11:24.360Z", "last_observed_at": "2026-02-19T08:11:24.360Z" },
"occurrence": { "seen_in": { "feed": true, "pivot": false }, "source_type": "feed", "feed_name": "urlhaus", "validation_status": "valid", "discovered_at": "2026-02-19T08:11:24.360Z" },
"pivot": { "depth": 0, "method": null, "actor": null, "confidence": 1.0 },
"evidence": [
{ "file": "config/hosts.txt", "line": 8, "snippet": "www.example.com" }
]
}
],
"query": { "indicator": { "type": "fqdn", "value": "www.example.com" } },
"meta": { "endpoint": "/v1/fqdns/{fqdn}/code-repos", "generated_at": "2026-07-05T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}IPs
GET /v1/ips/{ip}/info
A bounded overview of an IP: a summary.reputation headline (verdict + score), then an available object of existence flags (hosted_domains, code_repos, clusters), plus hosting, ownership, ASN, geo, and privacy-detection flags. summary.reputation and available.clusters come from the same signal as GET /v1/ips/{ip}/reputation. Enrichment fields are empty when the IP matches no known range; an un-enriched IP still returns its summary and flags. first_observed_at / last_observed_at are the IP's first-seen and most-recently-observed dates. history overlays the ownership-version timeline as data.history[].
Param | In | Type | Notes |
|---|---|---|---|
| path | string | IPv4/IPv6; malformed returns |
| query | temporal | overlay version history |
curl -X GET "https://app.malanta.ai/data/v1/ips/8.8.8.8/info" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"summary": { "reputation": { "verdict": "MALICIOUS", "malicious_score": 0.83, "malicious_score_band": "HIGH" } },
"available": { "hosted_domains": true, "code_repos": false, "clusters": true },
"ip_range": { "start_ip": "8.8.8.0", "end_ip": "8.8.8.255", "cidr": "8.8.8.0/24" },
"company": { "name": "Example Networks", "domain": "example-net.com" },
"asn": { "number": 15169, "org": "EXAMPLE-AS", "domain": "example-net.com" },
"ip_type": "HOSTING",
"geo": { "country": "US" },
"privacy": { "hosting": true, "proxy": false, "vpn": false, "tor": false, "relay": false, "service": null },
"first_observed_at": "2024-01-15T00:00:00Z", "last_observed_at": "2026-06-20T00:00:00Z"
},
"query": { "indicator": { "type": "ipv4-addr", "value": "8.8.8.8" } },
"meta": { "endpoint": "/v1/ips/{ip}/info", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}GET /v1/ips/{ip}/domains
The domains hosted on an IP. data carries total (the IP's full hosted-domain count), truncated (true when we hold only a sample of a very dense IP), and a keyset-paginated domains[], each entry with its own observed window.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | IPv4/IPv6 |
| query | ISO-8601 | narrow to domains whose window overlaps the range |
| query | boolean | every domain ever seen (current + past) |
| query | paging | default 500, max 1000 |
curl -X GET "https://app.malanta.ai/data/v1/ips/8.8.8.8/domains" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"total": 21127,
"truncated": true,
"domains": [
{ "domain": { "type": "domain-name", "value": "a.example" }, "first_observed_at": "2025-05-17T00:00:00Z", "last_observed_at": "2026-07-01T00:00:00Z" },
{ "domain": { "type": "domain-name", "value": "b.example" }, "first_observed_at": "2026-01-12T00:00:00Z", "last_observed_at": "2026-06-20T00:00:00Z" }
]
},
"query": { "indicator": { "type": "ipv4-addr", "value": "8.8.8.8" } },
"meta": { "endpoint": "/v1/ips/{ip}/domains", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": true, "next_cursor": "eyJkIjoiYi5leGFtcGxlIn0" }
}Page until pagination.has_more is false to retrieve everything stored for the IP; check truncated to know whether that is still a subset of the IP's full total.
POST /v1/ips/domains
Batch hosted-domains for 1–100 IPs. One group per IP, with the same total / truncated / domains as the single route.
curl -X POST "https://app.malanta.ai/data/v1/ips/domains" \
-H "x-api-key: malanta_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"ips": ["8.8.8.8", "1.1.1.1"]}'GET /v1/ips/{ip}/reputation
Malanta's verdict for an IP. An IP that is a member of a malicious cluster is MALICIOUS; any other IP returns the UNKNOWN shape. The top-level malicious_score reflects the strongest cluster; clusters[] lists the malicious clusters the IP belongs to (strongest first).
Param | In | Type | Notes |
|---|---|---|---|
| path | string | IPv4/IPv6; malformed returns |
curl -X GET "https://app.malanta.ai/data/v1/ips/203.0.113.7/reputation" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"reputation": { "verdict": "MALICIOUS", "labels": ["IOC"], "malicious_score": 0.16, "malicious_score_band": "LOW" },
"apt_names": [],
"ioc_sources": ["circl-misp-osint"],
"context": [],
"clusters": [ { "cluster_id": "5645115c-913f-550f-b179-b7366ef45bc6", "member_count": 8, "joined_at": "2026-02-01T00:00:00Z", "reputation": { "malicious_score": 0.16, "malicious_score_band": "LOW" } } ],
"timestamps": { "first_observed_at": "2026-01-13T00:00:00Z", "last_classified_at": "2026-06-20T02:14:09.880Z", "last_observed_at": "2026-06-20T02:14:09.880Z" }
},
"query": { "indicator": { "type": "ipv4-addr", "value": "203.0.113.7" } },
"meta": { "endpoint": "/v1/ips/{ip}/reputation", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/ips/reputation
Batch IP reputation for 1–100 IPs. Returns one entry per input, each with its own indicator.
curl -X POST "https://app.malanta.ai/data/v1/ips/reputation" \
-H "x-api-key: malanta_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"ips": ["203.0.113.7", "8.8.8.8"]}'GET /v1/ips/{ip}/code-repos
Public source-code repositories an IP appears in — same object as the domain code-repos endpoint. This is an exposure signal, not a verdict.
curl -X GET "https://app.malanta.ai/data/v1/ips/8.8.8.8/code-repos" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{
"repo": { "repo_id": "example-org/example-repo@master", "url": "https://github.com/example-org/example-repo", "platform": "github", "host": "github.com", "owner": "example-org", "stars": 1288, "forks": 143, "primary_language": "Python", "indicator_count": 3, "discovered_at": "2026-02-19T08:11:24.360Z", "last_observed_at": "2026-02-19T08:11:24.360Z" },
"occurrence": { "seen_in": { "feed": true, "pivot": false }, "source_type": "feed", "feed_name": "urlhaus", "validation_status": "valid", "discovered_at": "2026-02-19T08:11:24.360Z" },
"pivot": { "depth": 0, "method": null, "actor": null, "confidence": 1.0 },
"evidence": [
{ "file": "blocklists/ips.txt", "line": 120, "snippet": "8.8.8.8" }
]
}
],
"query": { "indicator": { "type": "ipv4-addr", "value": "8.8.8.8" } },
"meta": { "endpoint": "/v1/ips/{ip}/code-repos", "generated_at": "2026-07-05T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}Clusters
GET /v1/clusters
Every cluster an indicator belongs to. Pass ?indicator= as an IP or a registrable domain; the type is auto-detected. The response data is an array of clusters.
You can also browse the collection without an indicator by passing member_type (domain-name or ipv4-addr) plus optional filters. Omitting both indicator and member_type returns 400.
Param | In | Type | Notes |
|---|---|---|---|
| query | string | IPv4/IPv6 or registrable domain; omit for browse |
| query | enum |
|
| query | filters | repeatable |
| query | filters + paging |
curl -X GET "https://app.malanta.ai/data/v1/clusters?indicator=8.8.8.8" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{
"cluster_id": "…",
"cluster_class": { "value": "INFRASTRUCTURE" },
"cluster_type": "HOSTED_DOMAIN_ROTATION_CLUSTER",
"confidence": 0.92,
"confidence_band": "HIGH",
"lifecycle_status": "CONFIRMED",
"member_count": 184,
"members_truncated": false,
"first_built_at": "2026-01-13T08:00:00Z",
"last_updated_at": "2026-06-20T02:14:09Z",
"reputation": { "verdict": "MALICIOUS", "malicious_score": 0.97, "malicious_score_band": "HIGH", "labels": ["IOC"] },
"apt_names": [],
"ioc_sources": ["malanta"],
"members": [
{ "indicator": { "type": "ipv4-addr", "value": "8.8.8.8" }, "joined_at": "2026-05-20T00:00:00Z", "reputation": { "verdict": "MALICIOUS", "labels": ["IOC"] } }
]
}
],
"query": { "indicator": { "type": "ipv4-addr", "value": "8.8.8.8" } },
"meta": { "endpoint": "/v1/clusters", "generated_at": "…" },
"pagination": { "has_more": false, "next_cursor": null }
}Pass include_members=false for a lighter listing without member detail.
GET /v1/clusters/{cluster_id}
Retrieve a single cluster by its identifier.
curl -X GET "https://app.malanta.ai/data/v1/clusters/{cluster_id}" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"cluster_id": "33b3f438-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
"cluster_class": { "value": "INFRASTRUCTURE" },
"cluster_type": "HOSTED_DOMAIN_ROTATION_CLUSTER",
"confidence": 0.92,
"confidence_band": "HIGH",
"lifecycle_status": "CONFIRMED",
"member_count": 184,
"members_truncated": false,
"first_built_at": "2026-01-13T08:00:00Z",
"last_updated_at": "2026-06-20T02:14:09Z",
"reputation": { "verdict": "MALICIOUS", "malicious_score": 0.97, "malicious_score_band": "HIGH", "labels": ["IOC"] },
"apt_names": [],
"ioc_sources": ["malanta"],
"members": [
{ "indicator": { "type": "ipv4-addr", "value": "8.8.8.8" }, "joined_at": "2026-05-20T00:00:00Z", "reputation": { "verdict": "MALICIOUS", "labels": ["IOC"] } }
]
},
"query": { "indicator": null },
"meta": { "endpoint": "/v1/clusters/{cluster_id}", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}Code Repos
Reputation for public source-code repositories and the accounts (owners) that host them. Unlike the .../code-repos listing endpoints (which return the repositories an entity appears in), these score the repository or account itself: verdict, signal labels, a malicious_score, ioc_sources, context, and the account cluster it belongs to. Coverage today is GitHub; owner and repository names are case-insensitive. A verdict of MALICIOUS means the entity is flagged; UNKNOWN means "not flagged", never a claim that it is benign.
GET /v1/code-repos/{owner}/{repo}/reputation
Reputation for a single repository. reputation, ioc_sources, context, and timestamps describe the repository; clusters[0] describes its owner account (so an association-only repository can still carry a high cluster score contributed by a sibling repo). member_count is the number of flagged repositories under the account, and clusters is omitted when that count is 1. apt_names is currently always empty.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | account name; case-insensitive |
| path | string | repository name (no owner prefix) |
curl -X GET "https://app.malanta.ai/data/v1/code-repos/example-owner/example-repo/reputation" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"reputation": { "verdict": "MALICIOUS", "labels": ["IOPA"], "malicious_score": 0.76, "malicious_score_band": "HIGH" },
"apt_names": [],
"ioc_sources": ["urlhaus"],
"context": [
"reached via owner account 'example-owner' (pivot depth 1)",
"pivoted from example-owner/seed-repo",
"5 malicious indicators"
],
"clusters": [
{ "cluster_id": "392841bf-7480-55b6-88fc-ca7b0a0d257c", "member_count": 2, "joined_at": "2026-07-25T16:56:03.236Z", "reputation": { "malicious_score": 1.0, "malicious_score_band": "HIGH" } }
],
"timestamps": { "first_observed_at": "2026-07-25T16:56:03.236Z", "last_classified_at": "2026-07-25T16:56:03.236Z", "last_observed_at": "2026-07-25T16:56:03.236Z" }
},
"query": { "indicator": { "type": "code-repo", "value": "example-owner/example-repo" } },
"meta": { "endpoint": "/v1/code-repos/{owner}/{repo}/reputation", "generated_at": "2026-07-30T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}GET /v1/code-repos/{owner}/reputation
Account-wide verdict, folding in every flagged repository under the owner: labels and ioc_sources are unioned and malicious_score is the strongest repository's. Use this when you have identified the account but not the specific repository. context becomes an aggregate summary (one line per evidence class); for an account with a single flagged repository it reads the same as the per-repository route.
Param | In | Type | Notes |
|---|---|---|---|
| path | string | account name; case-insensitive |
curl -X GET "https://app.malanta.ai/data/v1/code-repos/example-owner/reputation" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"reputation": { "verdict": "MALICIOUS", "labels": ["IOPA", "IOC"], "malicious_score": 1.0, "malicious_score_band": "HIGH" },
"apt_names": [],
"ioc_sources": ["urlhaus"],
"context": [
"2 flagged repositories under this owner",
"1 feed seed (urlhaus)",
"1 reached via owner pivot (depth 1)",
"pivoted from example-owner/seed-repo",
"157 malicious indicators across 2 repositories"
],
"clusters": [
{ "cluster_id": "392841bf-7480-55b6-88fc-ca7b0a0d257c", "member_count": 2, "joined_at": "2026-07-25T14:27:50.657Z", "reputation": { "malicious_score": 1.0, "malicious_score_band": "HIGH" } }
],
"timestamps": { "first_observed_at": "2026-07-25T14:27:50.657Z", "last_classified_at": "2026-07-25T14:27:50.657Z", "last_observed_at": "2026-07-25T16:56:03.236Z" }
},
"query": { "indicator": { "type": "code-repo-owner", "value": "example-owner" } },
"meta": { "endpoint": "/v1/code-repos/{owner}/reputation", "generated_at": "2026-07-30T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/code-repos/reputation
Batch lookup for 1–100 entries, one group per input in request order. repos is a string array; scope is inferred per entry from the presence of a /: example-owner/example-repo is repository scope, example-owner is account scope. Each group echoes its own indicator, whose type (code-repo vs code-repo-owner) tells you which scope was applied. Deduped case-insensitively; one malformed entry rejects the whole request with 422.
Body field | Type | Notes |
|---|---|---|
| array<string> | 1–100 |
curl -X POST "https://app.malanta.ai/data/v1/code-repos/reputation" \
-H "x-api-key: malanta_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"repos": ["example-owner/example-repo", "other-owner", "unseen-owner"]}'An unseen entry returns the UNKNOWN shape (verdict: "UNKNOWN", empty labels/sources/clusters).
Certificates
Look up a certificate directly by its own identifier — independent of the host-scoped certificate endpoints. The returned certificate object has the same shape.
GET /v1/certificates/{certificate_id}
A single certificate by its certificate_id (a case-sensitive UUID). Returns 404 if unknown.
curl -X GET "https://app.malanta.ai/data/v1/certificates/1D551315-126A-417F-AB3B-0E0CAAEED9BA" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": {
"certificate_id": "1D551315-126A-417F-AB3B-0E0CAAEED9BA",
"serial_number": "120022056273139920459243120498800462479",
"serial_hex": "6563e1df3819f6ecf349f25a7ddda3c54ea",
"validity": { "not_before_at": "2026-06-11T22:22:58Z", "not_after_at": "2026-09-09T22:22:57Z" },
"subject": { "common_name": "www.example.com", "alternative_names": ["example.com", "www.example.com"] },
"issuer": { "common_name": "YR1", "organization": "Let's Encrypt", "country": "US", "locality": null },
"is_self_signed": false,
"fingerprints": { "sha1": "90808e86a0d9…", "sha256": "b868eaa376c6d6b612c0fda6cabf6805e0d5e57e5a3201130ccfafc4e1afb81c" },
"period": { "first_observed_at": "2026-06-12T00:00:00Z", "last_observed_at": "2026-06-14T08:42:39Z" }
},
"query": { "indicator": null },
"meta": { "endpoint": "/v1/certificates/{certificate_id}", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}GET /v1/certificates
Look certificates up by fingerprint or serial. Provide exactly one selector (otherwise 400). sha256 / sha1 are unique; serial_number (decimal) and serial_hex (hex) can match several (cursor-paged).
Param | In | Type | Notes |
|---|---|---|---|
| query | hex(64) | content hash |
| query | hex(40) | |
| query | decimal | decimal serial |
| query | hex | hex serial |
| query | paging | see Pagination |
curl -X GET "https://app.malanta.ai/data/v1/certificates?sha256=b868eaa376c6d6b612c0fda6cabf6805e0d5e57e5a3201130ccfafc4e1afb81c" \
-H "x-api-key: malanta_xxxxxxxxxxxxx"{
"data": [
{
"certificate_id": "94273995-fdaa-4b24-a1fd-e052e3520736",
"serial_number": "120022056273139920459243120498800462479",
"serial_hex": "6563e1df3819f6ecf349f25a7ddda3c54ea",
"validity": { "not_before_at": "2026-06-11T22:22:58Z", "not_after_at": "2026-09-09T22:22:57Z" },
"subject": { "common_name": "www.example.com", "alternative_names": ["example.com", "www.example.com"] },
"issuer": { "common_name": "YR1", "organization": "Let's Encrypt", "country": "US", "locality": null },
"is_self_signed": false,
"fingerprints": { "sha1": "90808e86a0d9…", "sha256": "b868eaa376c6d6b612c0fda6cabf6805e0d5e57e5a3201130ccfafc4e1afb81c" },
"period": { "first_observed_at": "2026-06-12T00:00:00Z", "last_observed_at": "2026-06-14T08:42:39Z" }
}
],
"query": { "indicator": null },
"meta": { "endpoint": "/v1/certificates", "generated_at": "2026-06-24T10:53:59.016Z" },
"pagination": { "has_more": false, "next_cursor": null }
}POST /v1/certificates
Batch certificate lookup — up to 100 lookups, mixed selector types allowed. Returns one group per requested {type, value}.
curl -X POST "https://app.malanta.ai/data/v1/certificates" \
-H "x-api-key: malanta_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"lookups":[{"type":"sha256","value":"b868eaa3…"},{"type":"serial_number","value":"9223390981080069519"}]}'STIX/TAXII Feed API
Retrieve general and targeted attack-infrastructure clusters in STIX 2.1 format over the TAXII 2.1 protocol.
This API uses Bearer token authentication (not the x-api-key header used by the other APIs).
Base URL: https://app.malanta.ai/feeds/taxii2
Authentication: Authorization: Bearer malanta_xxxxxxxxxxxxx
Endpoints
- Discovery —
GET /feeds/taxii2/default - Collections —
GET /feeds/taxii2/default/collections - Get objects —
GET /feeds/taxii2/default/collections/{collection_id}/objects
Query parameters
next— pagination cursor (returned in the previous response)
curl -s \
-H "Authorization: Bearer malanta_xxxxxxxxxxxxx" \
-H "Accept: application/json" \
"https://app.malanta.ai/feeds/taxii2/default/collections/targeting-pre-attack-indicators/objects"Paginated request
curl -s \
-H "Authorization: Bearer malanta_xxxxxxxxxxxxx" \
-H "Accept: application/json" \
"https://app.malanta.ai/feeds/taxii2/default/collections/targeting-pre-attack-indicators/objects?next=eyJwYWdlX251bSI6MiwicGFnZV9zeiI6MTAwfQ"STIX object types
The feed contains multiple STIX 2.1 object types:
- indicator — pre-attack indicators with pattern expressions
- infrastructure — attack-infrastructure elements (domains, IPs, certificates)
- relationship — links between indicators, infrastructure, and threat actors
- identity — targeted organizations and threat-actor identities
- grouping — attack-infrastructure clusters grouping related objects
Quick reference
- Always send your API key:
x-api-keyfor the Platform, IoPA Cluster, and Gold Query APIs;Authorization: Bearerfor the STIX/TAXII Feed. - Prefer the batch
POSTroutes when resolving more than one entity (1–100 per call). data: null(or an empty array) means "no data", not an error — only a non-2xx status is an error.- Treat
verdict: "UNKNOWN"as "not flagged" — never as "benign". - To page a collection, loop while
pagination.has_moreistrue, passingpagination.next_cursoras?cursor=. - Send a registrable domain to
/v1/domains/...; send a specific host to/v1/fqdns/....
Updated on: 20/08/2026
Thank you!