> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.malanta.ai/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Profile API - Integration Guide

# Malanta Profile API

**Gold Query · Domain / FQDN / IP Profile · Enrichment · Intelligence Attribution**

Version 1.0 | October 2026

---

## **Contents**

- [Overview](#2-overview)
    - [Base URL & authentication](#3-base-url-authentication)
    - [Endpoints](#3-endpoints)
- [Conventions](#2-conventions)
    - [Response envelope](#3-response-envelope)
    - [Empty / unknown observables](#3-empty-unknown-observables)
    - [Temporal parameters](#3-temporal-parameters)
    - [Domain vs host scope](#3-domain-vs-host-scope)
    - [Timestamps](#3-timestamps)
    - [Errors](#3-errors)
- [GET /v1/domains/{domain}/profile](#2-get-v1domainsdomainprofile)
    - [Path parameters](#3-path-parameters)
    - [Example request](#3-example-request)
    - [What you get in `data`](#3-what-you-get-in-data)
    - [Example response (abbreviated)](#3-example-response-abbreviated)
- [GET /v1/fqdns/{fqdn}/profile](#2-get-v1fqdnsfqdnprofile)
    - [Path parameters](#3-path-parameters)
    - [Example request](#3-example-request)
    - [Example `query` echo](#3-example-query-echo)
- [GET /v1/ips/{ip}/profile](#2-get-v1ipsipprofile)
    - [Path parameters](#3-path-parameters)
    - [Example request](#3-example-request)
    - [Example response (abbreviated)](#3-example-response-abbreviated)
- [Field reference](#2-field-reference)
    - [Envelope — `query` and `meta`](#3-envelope-query-and-meta)
    - [`data.profile.tags[]`](#3-dataprofiletags)
    - [`data.profile.state` (domain / FQDN only)](#3-dataprofilestate-domain-fqdn-only)
    - [`data.profile.registration` (domain / FQDN only)](#3-dataprofileregistration-domain-fqdn-only)
        - [`registration.current`](#4-registrationcurrent)
        - [`contacts[]` item](#4-contacts-item)
        - [`registration.changes`](#4-registrationchanges)
        - [`changes.summary`](#4-changessummary)
        - [`changes.significant[]` item](#4-changessignificant-item)
        - [`significant[].registration_state`](#4-significantregistration_state)
    - [`data.profile.network`](#3-dataprofilenetwork)
        - [Domain / FQDN shape](#4-domain-fqdn-shape)
        - [IP shape](#4-ip-shape)
    - [`data.profile.dns` (domain / FQDN only)](#3-dataprofiledns-domain-fqdn-only)
    - [`data.profile.services.endpoints[]`](#3-dataprofileservicesendpoints)
        - [`certificate` object](#4-certificate-object)
    - [`data.profile.tls`](#3-dataprofiletls)
    - [`data.profile.web`](#3-dataprofileweb)
        - [`web.page`](#4-webpage)
        - [`web.favicon`](#4-webfavicon)
        - [`web.resources.css`](#4-webresourcescss)
        - [`web.resources.javascript`](#4-webresourcesjavascript)
        - [`javascript.items[]` item](#4-javascriptitems-item)
    - [`data.related_observables[]`](#3-datarelated_observables)
        - [Observable item](#4-observable-item)
        - [Group-level `via`](#4-group-level-via)
    - [`data.intelligence`](#3-dataintelligence)

---

## **Overview**

Observable **Profile** endpoints are part of the [Gold Query API](https://help.malanta.ai/en/article/apis-1mtukvh/). They return a single consolidated, **current-state** enrichment view for a domain, host, or IP.

Use Profile when you want one call that assembles the investigation picture — registration state, WHOIS + significant changes, DNS, network/ASN, open services, TLS, web analysis, tags, related observables, and intelligence attribution.

Use the specialized Gold Query routes (reputation, WHOIS, certificates, DNS records, co-hosted domains, IP info, etc.) when you need deeper history, pagination, or batch lookups for a single data type.

### **Base URL & authentication**

Same as the rest of Gold Query:

| Item | Value |
| --- | --- |
| Base URL | `https://app.malanta.ai/data` |
| Auth header | `x-api-key: malanta_xxxxxxxxxxxxx` |

### **Endpoints**

| Method | Path | Scope |
| --- | --- | --- |
| `GET` | `/v1/domains/{domain}/profile` | Registrable domain (eTLD+1) |
| `GET` | `/v1/fqdns/{fqdn}/profile` | Any host; host-scoped enrichment, with state + registration from the apex |
| `GET` | `/v1/ips/{ip}/profile` | IPv4 or IPv6 address |

[↑ Back to top](#2-contents)

---

## **Conventions**

### **Response envelope**

Profile responses use `{ data, query, meta }` — there is **no** `pagination` field (profiles are single-object responses).

| Field | Meaning |
| --- | --- |
| `data` | The profile payload (`profile`, `related_observables`, `intelligence`) |
| `query.indicator` | Echo of what you asked for (`type`  • `value`; IPs may also include `ip_addr_hex`) |
| `meta` | `request_id`, `schema_version` (`2.0.0`), `endpoint`, `elapsed_ms`, `generated_at`, optional `coverage` |

### **Empty / unknown observables**

* HTTP **200** even when Malanta has little or no data for the indicator.
* Missing sections serialize as empty objects `{}` or empty arrays `[]` — not as omitted keys at the top level of `profile`.
* Only a non-2xx status is an error.

### **Temporal parameters**

`since`, `until`, and `history` are **not supported** on `/profile` and return **400**.

### **Domain vs host scope**

* Send a **registrable domain** (eTLD+1) to `/v1/domains/...`. A subdomain returns **422**.
* Send any **host** (apex or subdomain) to `/v1/fqdns/...`.
* On the FQDN route, network / DNS / services / TLS / web / tags / related observables / intelligence are scoped to the **exact host**. Only `profile.state` and `profile.registration` describe the registrable apex.

### **Timestamps**

All timestamps are ISO-8601 UTC with a trailing `Z` (for example `2026-08-08T06:11:24Z`).

### **Errors**

| Status | When |
| --- | --- |
| `401` / `403` | Missing or invalid API key |
| `400` | `since` / `until` / `history` on `/profile` |
| `422` | Malformed indicator (e.g. subdomain on `/domains`, invalid IP) |
| `5xx` | Upstream / service failure |

[↑ Back to top](#2-contents)

---

## **GET /v1/domains/{domain}/profile**

Consolidated current-state enrichment for a **registrable domain**.

### **Path parameters**

| Param | In | Type | Notes |
| --- | --- | --- | --- |
| `domain` | path | string | Registrable eTLD+1. Subdomain → `422` |

### **Example request**

```bash
curl -X GET "https://app.malanta.ai/data/v1/domains/example.com/profile" \
  -H "x-api-key: malanta_xxxxxxxxxxxxx"
```

### **What you get in `data`**

| Section | Contents |
| --- | --- |
| `profile.tags` | Infrastructure / classification tags |
| `profile.state` | Lifecycle: status, registration state, ownership transition, takedown |
| `profile.registration` | `current` WHOIS + `changes` (summary + significant timeline) |
| `profile.network` | Resolved IPs + per-network ASN / provider / range / PTR |
| `profile.dns` | A / MX / NS / TXT records |
| `profile.services` | Port probes (success and failure) with fixed endpoint schema |
| `profile.tls` | JARM fingerprint + negotiated TLS parameters |
| `profile.web` | Page response/content, favicon hashes, CSS / JS resources |
| `related_observables` | Groups: `resolves_to`, `redirects_to`, `shared_hosting` |
| `intelligence` | APT attribution + categorized attributes |

### **Example response (abbreviated)**

```json
{
  "data": {
    "profile": {
      "tags": [{ "key": "cdn", "name": "CDN", "family": "infrastructure" }],
      "state": {
        "domain_status": "inactive",
        "registration_state": "on_hold",
        "ownership_transition": null,
        "takedown": { "on_hold": true }
      },
      "registration": {
        "current": {
          "observed_at": "2026-08-08T06:11:24Z",
          "created_at": "2026-03-10T00:00:00Z",
          "updated_at": null,
          "expires_at": "2027-03-10T00:00:00Z",
          "registrar": {
            "id": "1068",
            "name": "Example Registrar",
            "whois_server": "whois.example-registrar.com",
            "url": null
          },
          "statuses": ["clientHold"],
          "name_servers": ["ns1.example.net"],
          "contacts": [
            {
              "role": "REGISTRANT",
              "name": null,
              "organization": "Example Org",
              "address": {
                "street": null,
                "city": null,
                "state": null,
                "postal_code": null,
                "country": "US"
              },
              "email": "owner@example.com",
              "email_local_part": "owner",
              "email_domain": "example.com",
              "phone": null,
              "fax": null
            }
          ]
        },
        "changes": {
          "summary": {
            "takedown": {
              "ever_observed": true,
              "first_observed_at": "2026-08-08T06:11:24Z",
              "latest_label": "Registrar hold (clientHold)"
            },
            "transition_dates": {
              "parked_since": null,
              "sinkholed_since": null
            },
            "event_counts": {
              "hold": 1,
              "lifecycle": 0,
              "name_server_change": 0,
              "ownership_change": 0,
              "registrar_change": 0,
              "status_change": 1
            }
          },
          "significant": [
            {
              "period": {
                "first_observed_at": "2026-08-08T06:11:24Z",
                "last_observed_at": "2026-08-08T06:11:24Z"
              },
              "primary_change": "TAKEDOWN",
              "changes": ["TAKEDOWN_HOLD", "STATUS_CHANGED"],
              "observation_count": 1,
              "primary_severity": null,
              "registration_state": {
                "registrar": { "name": null },
                "registrant": {
                  "name": null,
                  "company": null,
                  "country": null,
                  "email": "owner@example.com"
                },
                "statuses": ["clientHold"],
                "status_summary": {
                  "category": "ON_HOLD",
                  "label": "On Hold"
                },
                "name_servers": ["ns1.example.net"],
                "authority_created_at": null,
                "authority_updated_at": null,
                "authority_expires_at": "2027-03-10T00:00:00.000Z",
                "privacy_masked": true,
                "sinkholed": null,
                "takedown": {
                  "on_hold": true,
                  "label": "Registrar hold (clientHold)"
                }
              }
            }
          ]
        }
      },
      "network": {
        "ip_addresses": ["203.0.113.10"],
        "networks": [
          {
            "asn": {
              "number": 13335,
              "name": "Cloudflare, Inc.",
              "domain": "cloudflare.com"
            },
            "provider": {
              "name": "Cloudflare, Inc.",
              "domain": "cloudflare.com",
              "type": "hosting",
              "country": "US"
            },
            "address_range": {
              "cidr": "203.0.113.0/24",
              "start_ip": "203.0.113.0",
              "end_ip": "203.0.113.255"
            },
            "ip_addresses": ["203.0.113.10"],
            "ptr_records": ["edge-10.example.net"]
          }
        ]
      },
      "dns": {
        "a": [{ "address": "203.0.113.10" }],
        "mx": [],
        "ns": [],
        "txt": []
      },
      "services": {
        "endpoints": [
          {
            "ip": "203.0.113.10",
            "port": 443,
            "scheme": "https",
            "service": {
              "name": null,
              "product": null,
              "server": "cloudflare",
              "banner": null,
              "x_powered_by": null
            },
            "response": {
              "status_code": 200,
              "final_url": "https://www.example.com/",
              "redirect_location": null,
              "headers": ["server: cloudflare"]
            },
            "content": {
              "type": "text/html",
              "declared_length": null,
              "body_length": 48211,
              "body_sha256": null,
              "title": "Example",
              "excerpt": null
            },
            "certificate": {
              "certificate_id": null,
              "serial_number": null,
              "serial_hex": null,
              "validity": {
                "not_before_at": null,
                "not_after_at": "2026-12-01T00:00:00Z"
              },
              "subject": {
                "common_name": "example.com",
                "organization": null,
                "country": null,
                "alternative_names": ["*.example.com"]
              },
              "issuer": {
                "common_name": null,
                "organization": "Google Trust Services",
                "country": null,
                "locality": null,
                "state": null,
                "malanta_ca_id": null
              },
              "is_self_signed": null,
              "intelligences": {
                "sha1": null,
                "sha256": "c0ff…"
              },
              "period": {
                "first_observed_at": null,
                "last_observed_at": null
              }
            },
            "error": null
          }
        ]
      },
      "tls": {
        "jarm_fingerprint": "27d40d40d00040d00042d43d00041df04c41293ba84f6efe3a613b22f983e6",
        "negotiated": {
          "version": "TLS1.3",
          "cipher_suite": "TLS_AES_128_GCM_SHA256",
          "alpn": "h2",
          "handshake_protocol": "tls13_full",
          "server_name": "www.example.com"
        }
      },
      "web": {
        "page": {
          "response": {
            "response_status_code": 200,
            "final_url": "https://www.example.com/",
            "headers": ["server: cloudflare"]
          },
          "content": {
            "title": "Example",
            "body_length": 48211,
            "body_sha256": "9f2c…",
            "headings": ["Welcome to Example"],
            "links": ["https://www.example.com/about"]
          },
          "trackers": {}
        },
        "favicon": {
          "url": "https://www.example.com/favicon.ico",
          "final_url": null,
          "response_status_code": 200,
          "hashes": {
            "dhash": "0e1e3c3c1e0e0000",
            "mmh3": "-1255347784",
            "sha256": "5b2a…"
          }
        },
        "resources": {
          "css": {
            "aggregate_sha256": "4dec…",
            "class_set_hash": "9311…",
            "bytes_processed": 18342,
            "external_hosts": ["cdn.example.net"],
            "external_urls": ["https://cdn.example.net/site.css"],
            "fonts": ["Inter"],
            "resource_sha256": ["b391…"]
          },
          "javascript": {
            "aggregate_sha256": "2998…",
            "bytes_processed": 90211,
            "functionality_set_hash": "7c41…",
            "obfuscation": 0.62,
            "unattributed_capabilities": [
              { "id": "api:cookie", "dangerous": false }
            ],
            "items": [
              {
                "type": "inline",
                "url": null,
                "sha256": "2998…",
                "obfuscation": 0.62,
                "capabilities": [
                  { "id": "evt:domcontentloaded", "dangerous": false }
                ],
                "functions": []
              },
              {
                "type": "external",
                "url": "https://cdn.example.net/app.js",
                "sha256": "a1b2…",
                "obfuscation": 0.1,
                "capabilities": [
                  { "id": "net:fetch", "dangerous": false },
                  { "id": "dyn:eval", "dangerous": true }
                ],
                "functions": [
                  {
                    "name": "eval",
                    "sha256": "9a36…",
                    "capabilities": ["dyn:eval"]
                  }
                ]
              }
            ]
          }
        }
      }
    },
    "related_observables": [
      {
        "related_by": "resolves_to",
        "observables": [{ "type": "ipv4-addr", "value": "203.0.113.10" }]
      },
      {
        "related_by": "redirects_to",
        "observables": [
          {
            "type": "url",
            "value": "https://www.example.com/",
            "properties": {
              "redirect_method": "http",
              "redirect_persistence": "permanent",
              "response_status_code": 301
            }
          }
        ]
      },
      {
        "related_by": "shared_hosting",
        "via": { "type": "ipv4-addr", "value": "203.0.113.10" },
        "observables": [{ "type": "fqdn", "value": "cohost.example.org" }]
      }
    ],
    "intelligence": {}
  },
  "query": {
    "indicator": { "type": "domain-name", "value": "example.com" }
  },
  "meta": {
    "request_id": "3f1c2a9e-7d4b-4b8a-9a51-0c6f2e8d1b77",
    "schema_version": "2.0.0",
    "endpoint": "/v1/domains/{domain}/profile",
    "elapsed_ms": 412,
    "generated_at": "2026-10-14T09:00:00Z",
    "coverage": {
      "first_observed_at": "2026-08-26T08:32:43Z",
      "last_observed_at": "2026-08-26T08:32:43Z"
    }
  }
}
```

[↑ Back to top](#2-contents)

---

## **GET /v1/fqdns/{fqdn}/profile**

Same response shape as the domain Profile. Use this when you care about a **specific host**.
* Enrichment sections (network, DNS, services, TLS, web, tags, related observables, intelligence) are scoped to the exact `{fqdn}`.
* `profile.state` and `profile.registration` describe the host’s **registrable apex**.
* `query.indicator` echoes the original host with `type: "fqdn"`.

### **Path parameters**

| Param | In | Type | Notes |
| --- | --- | --- | --- |
| `fqdn` | path | string | Any well-formed host (apex or subdomain) |

### **Example request**

```bash
curl -X GET "https://app.malanta.ai/data/v1/fqdns/www.example.com/profile" \
  -H "x-api-key: malanta_xxxxxxxxxxxxx"
```

### **Example `query` echo**

```json
{
  "query": {
    "indicator": { "type": "fqdn", "value": "www.example.com" }
  }
}
```

[↑ Back to top](#2-contents)

---

## **GET /v1/ips/{ip}/profile**

Observable profile for an IP: network (ASN, provider, range, PTR), services, TLS, web (when available), tags, related observables, and intelligence.
IP profiles do **not** include domain-only sections (`state`, `registration`, `dns`).

### **Path parameters**

| Param | In | Type | Notes |
| --- | --- | --- | --- |
| `ip` | path | string | IPv4 or IPv6; malformed → `422` |

### **Example request**

```bash
curl -X GET "https://app.malanta.ai/data/v1/ips/104.16.69.86/profile" \
  -H "x-api-key: malanta_xxxxxxxxxxxxx"
```

### **Example response (abbreviated)**

```json
{
  "data": {
    "profile": {
      "tags": [],
      "network": {
        "asn": {
          "number": 13335,
          "name": "Cloudflare, Inc.",
          "domain": "cloudflare.com"
        },
        "provider": {
          "name": "Cloudflare, Inc.",
          "domain": "cloudflare.com",
          "type": "hosting",
          "country": "US"
        },
        "address_range": {
          "cidr": "104.16.0.0/16",
          "start_ip": "104.16.0.0",
          "end_ip": "104.16.255.255"
        },
        "ptr_records": ["edge-86.example.net"]
      },
      "services": {
        "endpoints": [
          {
            "ip": "104.16.69.86",
            "port": 22,
            "scheme": "tcp",
            "service": {
              "name": "ssh",
              "product": null,
              "server": null,
              "banner": null,
              "x_powered_by": null
            },
            "response": {
              "status_code": null,
              "final_url": null,
              "redirect_location": null,
              "headers": []
            },
            "content": {
              "type": null,
              "declared_length": null,
              "body_length": null,
              "body_sha256": null,
              "title": null,
              "excerpt": null
            },
            "certificate": null,
            "error": "ssh: handshake timeout"
          }
        ]
      },
      "tls": {
        "jarm_fingerprint": "27d40d40d00040d00042d43d00041df04c41293ba84f6efe3a613b22f983e6",
        "negotiated": {
          "version": "TLS1.3",
          "cipher_suite": "TLS_AES_128_GCM_SHA256",
          "alpn": "h2",
          "handshake_protocol": "tls13_full",
          "server_name": "www.example.com"
        }
      },
      "web": {}
    },
    "related_observables": [
      {
        "related_by": "shared_hosting",
        "observables": [
          { "type": "domain-name", "value": "example.com" }
        ]
      }
    ],
    "intelligence": {}
  },
  "query": {
    "indicator": {
      "type": "ipv4-addr",
      "value": "104.16.69.86",
      "ip_addr_hex": "00000000000000000000ffff68104556"
    }
  },
  "meta": {
    "request_id": "3f1c2a9e-7d4b-4b8a-9a51-0c6f2e8d1b77",
    "schema_version": "2.0.0",
    "endpoint": "/v1/ips/{ip}/profile",
    "elapsed_ms": 412,
    "generated_at": "2026-10-14T09:00:00Z",
    "coverage": {
      "first_observed_at": "2026-08-26T08:32:43Z",
      "last_observed_at": "2026-08-26T08:32:43Z"
    }
  }
}
```
**Note.** On IP profiles, `shared_hosting` groups list co-hosted domains/hosts and do **not** include a `via` object (the queried IP is already the hosting address). On domain/FQDN profiles, `shared_hosting` includes `via` pointing at the shared IP.

[↑ Back to top](#2-contents)

---

## **Field reference**

This section explains every field in the Profile response, grouped by section. Domain and FQDN profiles share the same shape; IP profiles omit domain-only sections (`state`, `registration`, `dns`) and use a flatter `profile.network`.

### **Envelope — `query` and `meta`**

| Field | Type | Description |
| --- | --- | --- |
| `query.indicator.type` | string | `domain-name`, `fqdn`, `ipv4-addr`, or `ipv6-addr` |
| `query.indicator.value` | string | The indicator you queried |
| `query.indicator.indicator_id` | string \| null | Stable id when available |
| `query.indicator.ip_addr_hex` | string \| null | Present for IP indicators (32-char IPv4-mapped hex key) |
| `meta.request_id` | string \| null | Request correlation id |
| `meta.schema_version` | string | Currently `2.0.0` |
| `meta.endpoint` | string | Route template, e.g. `/v1/domains/{domain}/profile` |
| `meta.elapsed_ms` | integer \| null | Server processing time in milliseconds |
| `meta.generated_at` | datetime | When the response was produced (UTC) |
| `meta.coverage.first_observed_at` | datetime \| null | Earliest observation for the entity’s available history span |
| `meta.coverage.last_observed_at` | datetime \| null | Latest observation for the entity’s available history span |

### **`data.profile.tags[]`**

| Field | Type | Description |
| --- | --- | --- |
| `key` | string \| null | Machine-stable tag key (e.g. `cdn`) |
| `name` | string \| null | Human-readable label |
| `family` | string \| null | Tag family (e.g. `infrastructure`) |

### **`data.profile.state` *(domain / FQDN only)***

Current lifecycle state of the registered domain. Empty → `{}`.

| Field | Type | Description |
| --- | --- | --- |
| `domain_status` | string \| null | High-level domain status (`active`,  `inactive`) |
| `registration_state` | string \| null | `unregistered`, `expired`, `on_hold`, `registered` |
| `ownership_transition` | string \| null | `sinkholed`, `parked`, or `null` |
| `takedown.on_hold` | boolean \| null | Whether the domain is currently on a takedown hold |
| `expired_days_ago` | integer | Present **only** when known; omitted when unknown |

### **`data.profile.registration` *(domain / FQDN only)***

Always shaped as `{ current, changes }`. If there is no current WHOIS, `current` is `{}`.

#### **`registration.current`**

Latest WHOIS record. Contacts: one per role (registrant, administrative, technical, billing); empty roles are dropped.

| Field | Type | Description |
| --- | --- | --- |
| `observed_at` | datetime \| null | When Malanta last observed this registration record |
| `created_at` | datetime \| null | Domain creation date from WHOIS |
| `updated_at` | datetime \| null | Domain last-updated date from WHOIS |
| `expires_at` | datetime \| null | Domain expiration date from WHOIS |
| `registrar.id` | string \| null | Registrar IANA / provider id when available |
| `registrar.name` | string \| null | Registrar name |
| `registrar.whois_server` | string \| null | Registrar WHOIS server hostname |
| `registrar.url` | string \| null | Registrar URL |
| `statuses` | string\[\] | EPP / RDAP status strings (e.g. `clientHold`) |
| `name_servers` | string\[\] | Authoritative name servers |
| `contacts[]` | array | Contact objects (see below) |

#### **`contacts[]` item**

| Field | Type | Description |
| --- | --- | --- |
| `role` | string | Contact role (e.g. `REGISTRANT`) |
| `name` | string \| null | Contact person name |
| `organization` | string \| null | Organization / company |
| `address.street` | string \| null | Street address |
| `address.city` | string \| null | City |
| `address.state` | string \| null | State / province |
| `address.postal_code` | string \| null | Postal code |
| `address.country` | string \| null | Country code / name |
| `email` | string \| null | Full email address |
| `email_local_part` | string \| null | Local part of the email |
| `email_domain` | string \| null | Domain part of the email |
| `phone` | string \| null | Phone number |
| `fax` | string \| null | Fax number |

#### **`registration.changes`**

Significant registration lifecycle timeline (always included — no `?history` flag).

#### **`changes.summary`**

| Field | Type | Description |
| --- | --- | --- |
| `takedown.ever_observed` | boolean \| null | Whether any takedown hold was ever observed |
| `takedown.first_observed_at` | datetime \| null | First observed takedown time |
| `takedown.latest_label` | string \| null | Human-readable latest takedown label |
| `transition_dates.parked_since` | datetime \| null | When parking was first observed |
| `transition_dates.sinkholed_since` | datetime \| null | When sinkholing was first observed |
| `event_counts.hold` | integer | Count of hold events |
| `event_counts.lifecycle` | integer | Count of lifecycle events |
| `event_counts.name_server_change` | integer | Count of name-server changes |
| `event_counts.ownership_change` | integer | Count of ownership changes |
| `event_counts.registrar_change` | integer | Count of registrar changes |
| `event_counts.status_change` | integer | Count of status changes |

#### **`changes.significant[]` item**

| Field | Type | Description |
| --- | --- | --- |
| `period.first_observed_at` | datetime \| null | Start of the change observation window |
| `period.last_observed_at` | datetime \| null | End of the change observation window |
| `primary_change` | string \| null | Primary change class (e.g. `FIRST`, `TAKEDOWN`) |
| `changes` | string\[\] | All change codes in this event (e.g. `TAKEDOWN_HOLD`, `STATUS_CHANGED`) |
| `observation_count` | integer \| null | How many observations contributed to this change |
| `primary_severity` | string \| null | Severity label when available |
| `registration_state` | object | Snapshot of registration at that point (see below) |

#### **`significant[].registration_state`**

| Field | Type | Description |
| --- | --- | --- |
| `registrar.name` | string \| null | Registrar name at that snapshot |
| `registrant.name` | string \| null | Registrant person name |
| `registrant.company` | string \| null | Registrant organization |
| `registrant.country` | string \| null | Registrant country |
| `registrant.email` | string \| null | Registrant email |
| `statuses` | string\[\] | Status strings at that snapshot |
| `status_summary.category` | string \| null | Normalized status category (e.g. `ON_HOLD`) |
| `status_summary.label` | string \| null | Human-readable status summary |
| `name_servers` | string\[\] | Name servers at that snapshot |
| `authority_created_at` | string \| null | Authority creation date as supplied by the source |
| `authority_updated_at` | string \| null | Authority update date as supplied by the source |
| `authority_expires_at` | string \| null | Authority expiration date as supplied by the source |
| `privacy_masked` | boolean \| null | Whether privacy/proxy masking was detected |
| `sinkholed` | boolean \| null | Whether sinkholing was indicated |
| `takedown.on_hold` | boolean \| null | Hold state at that snapshot |
| `takedown.label` | string \| null | Takedown label at that snapshot |

### **`data.profile.network`**

#### **Domain / FQDN shape**

| Field | Type | Description |
| --- | --- | --- |
| `ip_addresses` | string\[\] | All IPs currently associated with the observable |
| `networks[]` | array | Per-network blocks (ASN, provider, range, IPs, PTR) |
| `networks[].asn.number` | integer \| null | ASN number |
| `networks[].asn.name` | string \| null | ASN organization name |
| `networks[].asn.domain` | string \| null | ASN org domain |
| `networks[].provider.name` | string \| null | Hosting / network provider name |
| `networks[].provider.domain` | string \| null | Provider domain |
| `networks[].provider.type` | string \| null | Provider type (e.g. `hosting`) |
| `networks[].provider.country` | string \| null | Provider country |
| `networks[].address_range.cidr` | string \| null | CIDR for the address block |
| `networks[].address_range.start_ip` | string \| null | Start of the range |
| `networks[].address_range.end_ip` | string \| null | End of the range |
| `networks[].ip_addresses` | string\[\] | IPs in this network block that belong to the observable |
| `networks[].ptr_records` | string\[\] | Reverse-DNS (PTR) names for those IPs |

#### **IP shape**

Same ASN / provider / address_range / `ptr_records` fields, but **flat** under `profile.network` (no `ip_addresses` / `networks[]` wrapper). Empty → `{}`.

### **`data.profile.dns` *(domain / FQDN only)***

| Field | Type | Description |
| --- | --- | --- |
| `a[]` | array | A records; each item has `address` |
| `mx[]` | array | MX records; each item has `exchange` |
| `ns[]` | array | NS records; each item has `host` |
| `txt[]` | array | TXT records; each item has `value` |

### **`data.profile.services.endpoints[]`**

Fixed schema for every probe — successful **and** failed. Absent values are `null`, never omitted. `services` always keeps an `endpoints` array (possibly empty).

| Field | Type | Description |
| --- | --- | --- |
| `ip` | string \| null | IP that was probed |
| `port` | integer \| null | Port number |
| `scheme` | string \| null | Transport / URL scheme (e.g. `https`, `tcp`) |
| `service.name` | string \| null | Identified service name |
| `service.product` | string \| null | Product / software identity |
| `service.server` | string \| null | Server header / identity string |
| `service.banner` | string \| null | Raw banner when captured |
| `service.x_powered_by` | string \| null | `X-Powered-By` when present |
| `response.status_code` | integer \| null | HTTP status (null for non-HTTP probes) |
| `response.final_url` | string \| null | Final URL after following redirects during the probe |
| `response.redirect_location` | string \| null | Redirect `Location` when observed on this probe |
| `response.headers` | string\[\] | Response headers as `"name: value"` strings |
| `content.type` | string \| null | Content-Type |
| `content.declared_length` | integer \| null | Declared content length |
| `content.body_length` | integer \| null | Observed body length in bytes |
| `content.body_sha256` | string \| null | SHA-256 of the response body |
| `content.title` | string \| null | HTML title when extracted from this probe |
| `content.excerpt` | string \| null | Short body excerpt when available |
| `certificate` | object \| null | TLS certificate observed on this endpoint, or `null` |
| `error` | string \| null | Probe error message on failure; `null` on success |

#### **`certificate` object**

| Field | Type | Description |
| --- | --- | --- |
| `certificate_id` | null | Reserved; currently always `null` on Profile |
| `serial_number` | string \| null | Certificate serial (decimal string when available) |
| `serial_hex` | string \| null | Certificate serial in hex |
| `validity.not_before_at` | datetime \| null | Not-before |
| `validity.not_after_at` | datetime \| null | Not-after / expiry |
| `subject.common_name` | string \| null | Subject CN |
| `subject.organization` | string \| null | Subject organization |
| `subject.country` | string \| null | Subject country |
| `subject.alternative_names` | string\[\] | SANs |
| `issuer.common_name` | string \| null | Issuer CN |
| `issuer.organization` | string \| null | Issuer organization |
| `issuer.country` | string \| null | Issuer country |
| `issuer.locality` | string \| null | Issuer locality |
| `issuer.state` | string \| null | Issuer state |
| `issuer.malanta_ca_id` | string \| null | Malanta CA identifier when known |
| `is_self_signed` | boolean \| null | Whether the cert is self-signed |
| `intelligences.sha1` | string \| null | Certificate SHA-1 fingerprint |
| `intelligences.sha256` | string \| null | Certificate SHA-256 fingerprint |
| `period.first_observed_at` | datetime \| null | First time this cert was observed on the endpoint |
| `period.last_observed_at` | datetime \| null | Most recent observation |

### **`data.profile.tls`**

Empty → `{}`.

| Field | Type | Description |
| --- | --- | --- |
| `jarm_fingerprint` | string \| null | JARM TLS fingerprint |
| `negotiated.version` | string \| null | Negotiated TLS version (e.g. `TLS1.3`) |
| `negotiated.cipher_suite` | string \| null | Negotiated cipher suite |
| `negotiated.alpn` | string \| null | ALPN protocol (e.g. `h2`) |
| `negotiated.handshake_protocol` | string \| null | Handshake protocol detail |
| `negotiated.server_name` | string \| null | SNI / server name used in the handshake |

### **`data.profile.web`**

Web crawl / content analysis. Empty → `{}`.
**Redirects are not under ****`web`****.** They appear in `related_observables` with `related_by: "redirects_to"`.

#### **`web.page`**

| Field | Type | Description |
| --- | --- | --- |
| `response.response_status_code` | integer \| null | HTTP status of the page fetch |
| `response.final_url` | string \| null | Final URL after redirects |
| `response.headers` | string\[\] | Response headers as `"name: value"` strings |
| `content.title` | string \| null | HTML document title |
| `content.body_length` | integer \| null | Body length in bytes |
| `content.body_sha256` | string \| null | SHA-256 of the HTML body |
| `content.headings` | string\[\] | Page headings extracted from HTML (not HTTP headers) |
| `content.links` | string\[\] | Links extracted from the page |
| `trackers` | object | Map of tracker id → value when detected; otherwise `{}` |

#### **`web.favicon`**

| Field | Type | Description |
| --- | --- | --- |
| `url` | string \| null | Requested favicon URL |
| `final_url` | string \| null | Final favicon URL after redirects |
| `response_status_code` | integer \| null | HTTP status of the favicon fetch |
| `hashes.dhash` | string \| null | Perceptual dHash (**string**, preserves leading zeros) |
| `hashes.mmh3` | string \| null | MurmurHash3 (**string**; may be signed, e.g. `"-1255347784"`) |
| `hashes.sha256` | string \| null | SHA-256 of the favicon bytes |

#### **`web.resources.css`**

| Field | Type | Description |
| --- | --- | --- |
| `aggregate_sha256` | string \| null | Aggregate hash across processed CSS |
| `class_set_hash` | string \| null | Hash of the CSS class set |
| `bytes_processed` | integer \| null | Bytes of CSS processed |
| `external_hosts` | string\[\] | External hosts referenced by CSS |
| `external_urls` | string\[\] | External CSS URLs |
| `fonts` | string\[\] | Font families referenced |
| `resource_sha256` | string\[\] | Per-resource SHA-256 hashes |

#### **`web.resources.javascript`**

| Field | Type | Description |
| --- | --- | --- |
| `aggregate_sha256` | string \| null | Aggregate hash across processed scripts |
| `bytes_processed` | integer \| null | Bytes of JS processed |
| `functionality_set_hash` | string \| null | Hash of the observed functionality set |
| `obfuscation` | number \| null | Overall obfuscation score (0–1 style float when present) |
| `unattributed_capabilities[]` | array | Capabilities seen but not tied to a specific script item |
| `unattributed_capabilities[].id` | string | Capability id (e.g. `api:cookie`) |
| `unattributed_capabilities[].dangerous` | boolean | `true` marks a **security-sensitive** capability — not a malicious verdict |
| `items[]` | array | Per-script analysis (see below) |

#### **`javascript.items[]` item**

| Field | Type | Description |
| --- | --- | --- |
| `type` | string | `inline` or `external` |
| `url` | string \| null | Script URL for external scripts; `null` for inline |
| `sha256` | string \| null | Script content hash |
| `obfuscation` | number \| null | Per-script obfuscation score |
| `capabilities[]` | array | Capabilities attributed to this script (`id`, `dangerous`) |
| `functions[]` | array | Notable functions (`name`, `sha256`, `capabilities[]` of capability ids) |

### **`data.related_observables[]`**

Relationship edge groups. Each group has `related_by` + `observables[]`, and optionally `via`.

| `related_by` | Meaning | Notes |
| --- | --- | --- |
| `resolves_to` | DNS resolution targets (typically IPs) | Domain / FQDN |
| `redirects_to` | HTTP(S) redirect destinations | Observables often include `properties` (method, persistence, status) |
| `shared_hosting` | Other domains/hosts on the same IP | Domain/FQDN groups include `via` (the IP). IP groups have no `via`. |

#### **Observable item**

| Field | Type | Description |
| --- | --- | --- |
| `type` | string | STIX-style type (`ipv4-addr`, `fqdn`, `url`, `domain-name`, …) |
| `value` | string | Observable value |
| `properties` | object | Optional metadata (omitted when empty). Common on redirects: `redirect_method`, `redirect_persistence`, `response_status_code` |

#### **Group-level `via`**

| Field | Type | Description |
| --- | --- | --- |
| `via.type` / `via.value` | string | Intermediate observable (e.g. the shared IP for domain `shared_hosting`) |

### **`data.intelligence`**

Empty → `{}`.

| Field | Type | Description |
| --- | --- | --- |
| `attribution.apts` | string\[\] | APT / threat-actor names attributed to the observable |
| `attributes[]` | array | Categorized intelligence attributes |
| `attributes[].category` | string | Attribute category |
| `attributes[].value` | string | Attribute value |
| `attributes[].apts` | string\[\] | APTs associated with this attribute |
| `attributes[].countries` | string\[\] | Related countries when available |
| `attributes[].legitimacy_status` | string | Present only when set; omitted when `null` |

[↑ Back to top](#2-contents)

---

## **Quick reference**

* Base URL: `https://app.malanta.ai/data`
* Auth: `x-api-key: malanta_xxxxxxxxxxxxx`
* Endpoints: `GET /v1/domains/{domain}/profile`, `GET /v1/fqdns/{fqdn}/profile`, `GET /v1/ips/{ip}/profile`
* Envelope: `{ data, query, meta }` — **no** `pagination`
* `since` / `until` / `history` are **not supported** on `/profile` (return **400**)
* Unknown / unobserved entities still return **HTTP 200** with empty sections (`{}` / `[]`)
* There is no batch `POST` for Profile
* See also: [Malanta APIs](https://help.malanta.ai/en/article/apis-1mtukvh/) (Gold Query conventions, authentication, and the rest of the enrichment surface)

Support: [support@malanta.ai](mailto:support@malanta.ai)

[↑ Back to top](#2-contents)