Skip to main content

[EN] API Changelog 2.38.0

API Changelog — EASM Module (Attack Surface Management)

Written by Helyette Mehouelley

This changelog describes the REST API endpoints delivered with the EASM (Attack Surface Management) module. A new family of easm/*-style endpoints (mounted directly under /api/auth/) progressively replaces the legacy asm/* endpoints, with richer, more consistent data. The legacy asm/* endpoints remain available during the transition period.

Base URL: https://dashboard.cloud.patrowl.io/api/auth/

Authentication: All requests require an API token in the Authorization header:

Authorization: Token <your-API-token>

Scoping: Unless noted otherwise, every EASM resource is scoped to the assets you can see. All list/retrieve/export endpoints accept the same base filtering parameters:

Parameter

Type

Description

org_id

integer

Restrict results to one of your organizations. Defaults to all organizations you belong to.

asset_ids

string

Comma-separated Asset IDs. Restrict results to resources owned through these assets.

protections

string

Comma-separated protections (e.g. easm,pentested). Restrict to assets with one of these protections.

outside_business_hours

integer

Restrict results to assets with this outside-business-hours setting.

teams

string

Comma-separated Team IDs (Technologies and Technology detections only). Restrict to assets belonging to these teams.

Most list endpoints are paginated by page number (count/next/previous/results); CVEs are paginated by cursor (next/previous/results, with a cursor parameter). Every resource exposes a GET .../export (filter-based) and POST .../export (explicit ID list) endpoint returning a CSV (or JSON, via export_format=json) file.


1. Domains

Domains (and subdomains) discovered on your attack surface, with WHOIS and DNS record data.

1.1 List Domains

Item

Value

Method

GET

URL

/api/auth/domains

Permission

Member of an organization

Paginated with page numbers (count/next/previous/results).

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours

—

No

See base scoping parameters above.

ids

string

No

Comma-separated Domain IDs.

search

string

No

Case-insensitive search on the domain name.

is_top_domain

boolean

No

true for apex domains only (no parent); false for subdomains only.

parent_domain_id

integer

No

Only the direct subdomains of this Domain ID.

parent_asset_id

integer

No

Only the direct subdomains of the Domain owned by this Asset ID.

top_domain_id

integer

No

Only the subdomains belonging to this apex Domain ID.

ipv4_id

integer

No

Only the Domains currently resolving to this IPv4 ID (resolution seen in the last 90 days).

sorted_by

string

No

id, value, created_at, updated_at (prefix with - for descending).

limit / page

integer

No

Pagination.

Example request

GET /api/auth/domains?org_id=1&is_top_domain=true Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 42,       "value": "example.com",       "top_domain": null,       "parent_domain": null,       "www_domain": 43,       "registrar": "Example Registrar Inc.",       "registrar_id": 292,       "registrar_url": ["https://www.example-registrar.com"],       "registrar_status": ["clientTransferProhibited"],       "registrant_name": ["REDACTED FOR PRIVACY"],       "registrant_country": ["FR"],       "registrant_state_province": ["Ile-de-France"],       "dnsrecords": [         { "record_type": "A", "value": "203.0.113.10" },         { "record_type": "MX", "value": "mail.example.com" }       ],       "creation_dates": ["1997-08-14T04:00:00Z"],       "updated_dates": ["2025-08-10T09:12:00Z"],       "expiration_dates": ["2026-08-14T04:00:00Z"],       "name_servers": ["ns1.example.com", "ns2.example.com"],       "whois_text": "Domain Name: EXAMPLE.COM\n...",       "created_at": "2025-01-10T09:00:00Z",       "updated_at": "2025-08-10T09:12:00Z"     }   ] }

top_domain, parent_domain and www_domain are Domain IDs (or null). dnsrecords is a flattened list built from the raw DNS lookup; registrar is a string ("" when unknown); registrar_url/registrar_status/registrant*/creation_dates/updated_dates/expiration_dates/name_servers are arrays because WHOIS can report more than one value per field.

Possible status codes

Code

Description

200

Success. Empty page if filters match nothing.

401

Unauthorized.

403

Not a member of the requested organization.


1.2 Get a Domain by ID

Item

Value

Method

GET

URL

/api/auth/domains/{id}

Permission

Member of an organization

Same response shape as a single item of the list above.

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

Domain not found or not accessible.


1.3 Export Domains

Item

Value

Method

GET or POST

URL

/api/auth/domains/export

Permission

Member of an organization

GET exports every Domain matching the list filters above (including parent_asset_id/parent_domain_id to export subdomains, or ipv4_id to export the Domains resolving to an IPv4). POST exports only the given IDs.

Query parameters: same as List, plus export_format (csv default, or json).

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

Domain IDs to export. At least one.

Possible status codes

Code

Description

200

File returned.

400

Invalid/empty ids (POST).

401

Unauthorized.

404

One or more requested IDs are not accessible.


2. IPv4 addresses

IPv4 addresses owned by your assets, as well as contextualized addresses (third-party IPs your domains resolve to, which you do not own).

2.1 List IPv4 addresses

Item

Value

Method

GET

URL

/api/auth/ipv4s

Permission

Member of an organization

Includes both the addresses you own and contextualized IPs your domains resolve to. Filter on is_owned to keep only addresses you own.

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours

—

No

See base scoping parameters above.

ids

string

No

Comma-separated IPv4 IDs.

search

string

No

Text search on the IP value.

value

string

No

Exact IPv4 address.

type

string

No

IP type: cdn, saas, waf, cloud, static, other, private, unknown.

in_blocklist

boolean

No

Only IPs present on a blocklist.

asn_id

integer

No

Filter by ASN ID.

is_owned

boolean

No

true: only IPs you own. false: only contextualized IPs.

domain_asset_id

integer

No

Only IPs resolved from the Domain owned by this Asset ID.

sorted_by

string

No

id, value, type, created_at, updated_at.

Example request

GET /api/auth/ipv4s?org_id=1&is_owned=true Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 501,       "value": "203.0.113.10",       "asn": 64500,       "type": "static",       "in_blocklist": false,       "blocklists": [],       "provider": {         "cdn": "",         "cloud": "AWS",         "saas": "",         "waf": ""       },       "created_at": "2026-01-05T09:00:00Z",       "updated_at": "2026-08-14T07:12:00Z"     }   ] }

asn is the numeric ASN ID (use GET /api/auth/asns/{asn} to resolve its details), not the AS number itself. The provider fields (cdn, cloud, saas, waf) are always strings: an empty string "" means no provider was detected for that category.

Possible status codes

Code

Description

200

Success. Empty page if the filters match nothing.

401

Unauthorized.

403

Caller is not a member of the requested organization.


2.2 Retrieve an IPv4 address

Item

Value

Method

GET

URL

/api/auth/ipv4s/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

IPv4 not found or not accessible.


2.3 Export IPv4 addresses

Item

Value

Method

GET or POST

URL

/api/auth/ipv4s/export

Permission

Member of an organization

GET — same filters as List, plus export_format. POST — explicit list of IDs.

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

IPv4 IDs to export.

Possible status codes

Code

Description

200

File returned.

400

POST with invalid/empty ids.

401

Unauthorized.

403

Caller is not a member of the requested organization.

404

POST: one or more ids are not accessible.


3. Resolutions

The links between a Domain and the IPv4 addresses it resolves to.

Visibility window: GET /api/auth/resolutions only returns resolutions last observed within the past 90 days. A resolution that goes stale beyond that window is no longer returned by the API (though the record is kept internally). Within that 90-day window, the resolves field tells you whether the resolution is still considered current (seen again within the last 15 days) — see below.

3.1 List resolutions

Item

Value

Method

GET

URL

/api/auth/resolutions

Permission

Member of an organization

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours

—

No

See base scoping parameters above.

ids

string

No

Comma-separated resolution IDs.

search

string

No

Text search on the domain or IPv4 value.

domain_id

integer

No

Filter by Domain ID.

ipv4_id

integer

No

Filter by IPv4 ID.

domain_value

string

No

Exact domain value (case-insensitive).

ipv4_value

string

No

Exact IPv4 address.

resolves

boolean

No

true: resolution observed within the last 15 days. false: older (but still within the 90-day visibility window).

first_resolved_at__gte / __lte

datetime

No

First observed on/after or on/before this date.

last_resolved_at__gte / __lte

datetime

No

Last observed on/after or on/before this date.

sorted_by

string

No

id, domain_value, ipv4_value, first_resolved_at, last_resolved_at, created_at, updated_at.

Example request

GET /api/auth/resolutions?org_id=1&resolves=true Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 9001,       "domain": {         "id": 12,         "value": "www.acme.example"       },       "ipv4": {         "id": 501,         "value": "203.0.113.10",         "type": "static"       },       "first_resolved_at": "2026-01-05T09:00:00Z",       "last_resolved_at": "2026-09-20T03:00:00Z",       "resolves": true,       "created_at": "2026-01-05T09:00:00Z",       "updated_at": "2026-09-20T03:00:00Z"     }   ] }

There is no state field on this resource: freshness is expressed only through resolves and the last_resolved_at timestamp.

Possible status codes

Code

Description

200

Success. Empty page if the filters match nothing.

401

Unauthorized.

403

Caller is not a member of the requested organization.


3.2 Retrieve a resolution

Item

Value

Method

GET

URL

/api/auth/resolutions/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

Resolution not found, not accessible, or outside the 90-day visibility window.


3.3 Export resolutions

Item

Value

Method

GET or POST

URL

/api/auth/resolutions/export

Permission

Member of an organization

GET — same filters as List, plus export_format. POST — explicit list of IDs.

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

Resolution IDs to export.

Possible status codes

Code

Description

200

File returned.

400

POST with invalid/empty ids.

401

Unauthorized.

403

Caller is not a member of the requested organization.

404

POST: one or more ids are not accessible.


4. ASNs

Autonomous systems (ASN) associated with your assets' IPv4 addresses.

4.1 List ASNs

Item

Value

Method

GET

URL

/api/auth/asns

Permission

Member of an organization

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours

—

No

See base scoping parameters above.

ids

string

No

Comma-separated ASN IDs.

search

string

No

Text search on the number, description, CIDR, or registry.

number

string

No

ASN number, plain (64500) or prefixed (AS64500), case-insensitive.

cidr

string

No

Partial (contains) match on the CIDR block.

registry

string

No

Exact registry (e.g. RIPE, ARIN), case-insensitive.

country_code

string

No

Exact country code, case-insensitive.

sorted_by

string

No

id, number, cidr, registry, country_code, ipv4_count, created_at, updated_at.

Example request

GET /api/auth/asns?org_id=1&country_code=FR Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 77,       "number": "AS64500",       "cidr": "203.0.113.0/24",       "registry": "RIPE",       "description": "ACME-NET",       "country_code": "FR",       "ipv4_count": 12,       "created_at": "2026-01-05T09:00:00Z",       "updated_at": "2026-08-14T07:12:00Z"     }   ] }

number is a human-readable, AS-prefixed string (e.g. "AS64500"), not a bare integer. ipv4_count is the number of IPv4 addresses visible to the caller that belong to this ASN.

Possible status codes

Code

Description

200

Success. Empty page if the filters match nothing.

401

Unauthorized.

403

Caller is not a member of the requested organization.


4.2 Retrieve an ASN

Item

Value

Method

GET

URL

/api/auth/asns/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

ASN not found or not accessible.


4.3 Export ASNs

Item

Value

Method

GET or POST

URL

/api/auth/asns/export

Permission

Member of an organization

GET — same filters as List, plus export_format. POST — explicit list of IDs.

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

ASN IDs to export.

Possible status codes

Code

Description

200

File returned.

400

POST with invalid/empty ids.

401

Unauthorized.

403

Caller is not a member of the requested organization.

404

POST: one or more ids are not accessible.


5. Services

Network services (open ports) detected on scanned assets.

5.1 List Services

Item

Value

Method

GET

URL

/api/auth/services

Permission

Member of an organization

Paginated with page numbers. The banner text is only served by the detail route; the list only reports its presence through has_banner.

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours

—

No

See base scoping parameters above.

ids

string

No

Comma-separated Service IDs.

search

string

No

Searches the service name, the banner text, and the port number.

webserver

integer

No

Only Services exposing this WebServer ID.

has_certificate

boolean

No

Only Services with (or without) a TLS certificate.

certificate_ids

string

No

Comma-separated Certificate IDs.

technology_ids

string

No

Comma-separated Technology IDs detected on the service.

asset_type

string

No

Asset type of the underlying asset: domain, ip, or other.

protocol

string

No

tcp or udp.

state

string

No

open or closed. A Service not re-observed for 14 days is closed automatically.

availability

string

No

Comma-separated asset availability values.

is_ssl

boolean

No

Only services using TLS.

port_number

integer

No

Exact port number.

sorted_by

string

No

id, value, name, port_number, protocol, state, last_seen, created_at, updated_at.

Example request

GET /api/auth/services?org_id=1&state=open&protocol=tcp Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 501,       "value": "203.0.113.10",       "asset_type": "ip",       "name": "https",       "protocol": "tcp",       "port_number": 443,       "state": "open",       "is_ssl": true,       "has_banner": true,       "certificate": {         "id": 88,         "serial_number": "0A1B2C3D4E5F",         "is_expired": false,         "is_mismatched": false,         "is_selfsigned": false       },       "webservers": [         {           "id": 77,           "url": "https://example.com/",           "server": "nginx",           "title": "Example Domain",           "path": "/",           "jarm": "27d27d27d29d27d1dc27d27d27d27d..."         }       ],       "last_seen": "2026-09-20T06:00:00Z",       "created_at": "2025-01-10T09:00:00Z",       "updated_at": "2026-09-20T06:00:00Z"     }   ] }

asset_type is the type of the underlying asset: domain, ip, or other. certificate is null when no TLS certificate is attached to the Service, even on a TLS port with is_ssl: true.

A state of closed means the Service was not re-observed in the last 14 days (or is otherwise confirmed closed).

Possible status codes

Code

Description

200

Success. Empty page if filters match nothing.

401

Unauthorized.

403

Not a member of the requested organization.


5.2 Get a Service by ID

Item

Value

Method

GET

URL

/api/auth/services/{id}

Permission

Member of an organization

Same fields as the list item, plus the full banner text.

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

Service not found or not accessible.


5.3 Export Services

Item

Value

Method

GET or POST

URL

/api/auth/services/export

Permission

Member of an organization

GET exports open Services only, matching the list filters. POST exports the explicit list of IDs regardless of state. Both include the full banner text.

Possible status codes

Code

Description

200

File returned.

400

Invalid/empty ids (POST).

401

Unauthorized.

404

One or more requested IDs are not accessible.


6. Web servers

Web servers detected on the services exposed by your assets.

6.1 List Web servers

Item

Value

Method

GET

URL

/api/auth/webservers

Permission

Member of an organization

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours

—

No

See base scoping parameters above.

ids

string

No

Comma-separated Web server IDs.

search

string

No

Text search on the asset value, URL, title, path, and server.

value

string

No

Exact asset value (case-insensitive).

url

string

No

Exact URL (case-insensitive).

server

string

No

Exact filter on the server header.

title

string

No

Exact filter on the page title.

jarm

string

No

Exact filter on the JARM fingerprint.

status_code

integer

No

Exact filter on the returned HTTP status code.

service_id

integer

No

Filter on the associated Service ID.

is_ssl

boolean

No

Filter on whether the underlying Service uses SSL.

state

string

No

Filter on the underlying Service's state (open/closed).

asset_id

integer

No

Restrict to Web servers belonging to this Asset.

sorted_by

string

No

id, value, url, server, title, status_code, port_number, created_at, updated_at.

Example request

GET /api/auth/webservers?org_id=1&is_ssl=true Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 42,       "value": "www.acme.example",       "service": {         "id": 100,         "port_number": 443,         "protocol": "tcp",         "is_ssl": true,         "state": "open"       },       "url": "https://www.acme.example/",       "server": "nginx/1.25.3",       "path": "/",       "title": "Acme — Home",       "response_time": null,       "status_code": 200,       "content_length": 15234,       "content_type": "text/html; charset=utf-8",       "jarm": "27d3ed3ed0003ed1dc42d43d00041d4689e...",       "favicon_hash": "-1179287843",       "created_at": "2026-02-20T10:00:00Z",       "updated_at": "2026-08-14T07:12:00Z"     }   ] }

response_time is an integer, or null when it was not measured.

Possible status codes

Code

Description

200

Success. Empty page if the filters match nothing.

401

Unauthorized.

403

Caller is not a member of the requested organization.


6.2 Retrieve a Web server

Item

Value

Method

GET

URL

/api/auth/webservers/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

Web server not found or not accessible.


6.3 Export Web servers

Item

Value

Method

GET or POST

URL

/api/auth/webservers/export

Permission

Member of an organization

GET exports according to the same filters as List, plus export_format. POST exports an explicit list of IDs.

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

Web server IDs to export.

Possible status codes

Code

Description

200

File returned.

400

POST with invalid/empty ids.

401

Unauthorized.

403

Caller is not a member of the requested organization.

404

POST: one or more ids are not accessible.


7. Certificates

TLS certificates detected on your assets' services. A Certificate is unique by serial number and is reported once, whatever the number of Services presenting it. Each row carries the raw certificate material.

7.1 List Certificates

Item

Value

Method

GET

URL

/api/auth/certificates

Permission

Member of an organization

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours

—

No

See base scoping parameters above.

ids

string

No

Comma-separated Certificate IDs.

search

string

No

Searches the serial number, the raw certificate text, and the value of the assets presenting it.

serial_number

string

No

Exact match on the serial number (colon-insensitive and case-insensitive).

is_expired

boolean

No

Filter expired / non-expired certificates.

is_mismatched

boolean

No

Filter certificates whose name doesn't match the domain.

is_selfsigned

boolean

No

Filter self-signed certificates.

asset_value

string

No

Exact (case-insensitive) match on the value of an asset presenting the certificate.

port_number

integer

No

Filter by the port of a service presenting the certificate.

sorted_by

string

No

id, serial_number, port_number, asset_value, created_at, updated_at.

Example request

GET /api/auth/certificates?is_expired=false&sorted_by=-created_at Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 42,       "serial_number": "0A:1B:2C:3D:4E:5F",       "services": [         {           "id": 501,           "value": "app.example.com",           "asset_type": "domain",           "protocol": "tcp",           "port_number": 443         }       ],       "is_expired": false,       "is_mismatched": false,       "is_selfsigned": false,       "created_at": "2026-08-01T09:00:00Z",       "updated_at": "2026-09-10T09:00:00Z",       "data_text": "Certificate:\n    Data:\n        Version: 3 ...",       "data_pem": "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----",       "data_parsed": {         "subject": { "CN": "app.example.com" },         "issuer": { "CN": "Let's Encrypt" },         "not_before": "2026-08-01T00:00:00Z",         "not_after": "2026-10-30T00:00:00Z"       }     }   ] }

Possible status codes

Code

Description

200

Success. Empty page if filters match nothing.

401

Unauthorized.

403

Not a member of any organization.


7.2 Retrieve a Certificate

Item

Value

Method

GET

URL

/api/auth/certificates/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

403

Not a member of any organization.

404

Certificate not found or not accessible.


7.3 Export Certificates

GET exports according to the same filters as List; POST exports only the given IDs. The raw certificate fields (data_text, data_pem, data_parsed) are excluded from the export.

Item

Value

Method

GET or POST

URL

/api/auth/certificates/export

Permission

Member of an organization

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

Certificate IDs to export. At least one.

Possible status codes

Code

Description

200

File returned.

400

POST with invalid/empty ids.

401

Unauthorized.

403

Not a member of any organization.

404

One or more requested ids are not accessible.


8. Vendors

The catalog of vendors behind the technologies detected on your assets (a global catalog, not scoped by organization or asset).

8.1 List Vendors

Item

Value

Method

GET

URL

/api/auth/vendors

Permission

Member of an organization

Query parameters

Parameter

Type

Required

Description

ids

string

No

Comma-separated Vendor IDs.

search

string

No

Case-insensitive search on the vendor name.

sorted_by

string

No

id, name, products_count, created_at, updated_at.

Example request

GET /api/auth/vendors?search=microsoft&sorted_by=-products_count Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 7,       "name": "Microsoft",       "products_count": 12,       "created_at": "2026-08-01T09:00:00Z",       "updated_at": "2026-09-10T09:00:00Z"     }   ] }

products_count is the number of Products referenced for this Vendor.

Possible status codes

Code

Description

200

Success. Empty page if filters match nothing.

401

Unauthorized.

403

Not a member of any organization.


8.2 Retrieve a Vendor

Item

Value

Method

GET

URL

/api/auth/vendors/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

403

Not a member of any organization.

404

Vendor not found.


8.3 Export Vendors

GET exports according to the same filters as List; POST exports only the given IDs.

Item

Value

Method

GET or POST

URL

/api/auth/vendors/export

Permission

Member of an organization

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

Vendor IDs to export. At least one.

Possible status codes

Code

Description

200

File returned.

400

POST with invalid/empty ids.

401

Unauthorized.

403

Not a member of any organization.

404

One or more requested ids are not accessible.


9. Products

The catalog of products (application, operating system, hardware) belonging to a Vendor, used to identify the technologies detected on your assets (a global catalog, not scoped by organization or asset).

9.1 List Products

Item

Value

Method

GET

URL

/api/auth/products

Permission

Member of an organization

Query parameters

Parameter

Type

Required

Description

ids

string

No

Comma-separated Product IDs.

search

string

No

Case-insensitive search on the product name or its vendor's name.

vendor

string

No

Comma-separated Vendor IDs. Restrict to products of these vendors.

type

string

No

Product type: application, operating_system, hardware.

sorted_by

string

No

id, name, vendor, type, created_at, updated_at.

Example request

GET /api/auth/products?type=operating_system&vendor=7 Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 101,       "vendor": { "id": 7, "name": "Microsoft" },       "name": "Windows Server",       "type": "operating_system",       "partial_cpe": "cpe:2.3:o:microsoft:windows_server",       "created_at": "2026-08-01T09:00:00Z",       "updated_at": "2026-09-10T09:00:00Z"     }   ] }

Possible status codes

Code

Description

200

Success. Empty page if filters match nothing.

401

Unauthorized.

403

Not a member of any organization.


9.2 Retrieve a Product

Item

Value

Method

GET

URL

/api/auth/products/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

403

Not a member of any organization.

404

Product not found.


9.3 Export Products

GET exports according to the same filters as List; POST exports only the given IDs.

Item

Value

Method

GET or POST

URL

/api/auth/products/export

Permission

Member of an organization

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

Product IDs to export. At least one.

Possible status codes

Code

Description

200

File returned.

400

POST with invalid/empty ids.

401

Unauthorized.

403

Not a member of any organization.

404

One or more requested ids are not accessible.


10. Technologies

Technologies (software/hardware products and versions) detected on your assets. One row per distinct product/version combination — see §11 for the per-detection view (which asset, which service, when).

10.1 List Technologies

Item

Value

Method

GET

URL

/api/auth/technologies

Permission

Member of an organization

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours, teams

—

No

See base scoping parameters above.

product_ids

string

No

Comma-separated Product IDs.

vendor_ids

string

No

Comma-separated Vendor IDs.

version

string

No

Case-insensitive substring match on the detected version.

product_type

string

No

Product category (see the Products resource).

is_relevant

boolean

No

Only Technologies with at least one detection flagged as relevant/irrelevant.

source

string

No

Only Technologies with a detection from this source: auto or custom.

search

string

No

Matches product name, vendor name, or version (space-separated terms, AND across words).

asset_id

integer

No

Only the Technologies detected on this Asset ID.

sorted_by

string

No

vendor, product, version.

Example request

GET /api/auth/technologies?org_id=1&product_ids=12 Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 900,       "product": {         "id": 12,         "name": "nginx",         "vendor": { "id": 4, "name": "F5, Inc." }       },       "version": "1.25.3",       "partial_cpe": "cpe:2.3:a:f5:nginx:1.25.3",       "created_at": "2025-01-10T09:00:00Z",       "updated_at": "2026-09-20T06:00:00Z"     }   ] }

Possible status codes

Code

Description

200

Success. Empty page if filters match nothing.

401

Unauthorized.

403

Not a member of the requested organization.


10.2 Get a Technology by ID

Item

Value

Method

GET

URL

/api/auth/technologies/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

Technology not found or not accessible.


10.3 Retrieve aggregates for a list of Technologies

Returns the asset count, CVE count, and last-seen date for a batch of Technology IDs — useful to build a summary view without one request per Technology.

Item

Value

Method

POST

URL

/api/auth/technologies/aggregates

Permission

Member of an organization

Query parameters: same scoping parameters as List (org_id, asset_ids, protections, outside_business_hours, teams).

Request body (JSON)

Field

Type

Required

Description

ids

array of integers

Yes

Technology IDs to compute counters for. At least one, max 500.

Example request

POST /api/auth/technologies/aggregates?org_id=1 Authorization: Token <your-API-token> Content-Type: application/json Accept: application/json  {   "ids": [900, 901] }

Example response 200 OK

{   "counts": [     {       "id": 900,       "assets": 12,       "cves": 3,       "last_seen_at": "2026-09-20T06:00:00Z"     },     {       "id": 901,       "assets": 0,       "cves": 0,       "last_seen_at": null     }   ] }

Possible status codes

Code

Description

200

Success.

400

Invalid payload (missing/empty ids, or more than 500).

401

Unauthorized.


10.4 Export Technologies

GET exports according to the same filters as List; POST exports only the given IDs.

Item

Value

Method

GET or POST

URL

/api/auth/technologies/export

Permission

Member of an organization

Possible status codes

Code

Description

200

File returned.

400

Invalid/empty ids (POST).

401

Unauthorized.

404

One or more requested IDs are not accessible.


11. Technology Detections — new

New resource. Where §10 (Technologies) gives you one row per distinct product/version, this resource gives you every individual detection: which asset, which service, which scanner, and when. Use it to answer "where exactly is this technology running" rather than "is this technology present at all".

Automatic lifecycle: an automatically-detected (non-CUSTOM source) detection that hasn't been re-observed for 14 days is automatically marked is_relevant: false — mirroring the Service auto-close behavior described in §5. Detections you added manually (source: "custom") are never auto-demoted this way, and a detection on an asset that is no longer scanned is left untouched rather than being guessed stale.

11.1 List Technology detections

Item

Value

Method

GET

URL

/api/auth/technology-detections

Permission

Member of an organization

Query parameters

Parameter

Type

Required

Description

org_id, asset_ids, protections, outside_business_hours, teams

—

No

See base scoping parameters above.

ids

string

No

Comma-separated Technology detection IDs.

technology_ids

string

No

Comma-separated Technology IDs.

product_ids

string

No

Comma-separated Product IDs.

vendor_ids

string

No

Comma-separated Vendor IDs.

service_ids

string

No

Comma-separated Service IDs.

version

string

No

Case-insensitive substring match on the detected version.

is_relevant

boolean

No

Only detections flagged as relevant (or irrelevant).

source

string

No

Only detections from this source: auto or custom.

search

string

No

Matches the asset value, vendor name, product name, version, or service name (space-separated terms, AND across words).

first_seen_at__gte / __lte

datetime

No

First seen on/after or on/before this date.

last_seen_at__gte / __lte

datetime

No

Last seen on/after or on/before this date.

sorted_by

string

No

id, value, vendor, product, version, port_number, source, confidence, is_relevant, first_seen_at, last_seen_at.

Example request

GET /api/auth/technology-detections?org_id=1&technology_ids=900 Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "count": 1,   "next": null,   "previous": null,   "results": [     {       "id": 5001,       "value": "203.0.113.10",       "asset_type": "ip",       "technology": {         "id": 900,         "product": {           "id": 12,           "name": "nginx",           "vendor": { "id": 4, "name": "F5, Inc." }         },         "version": "1.25.3",         "partial_cpe": "cpe:2.3:a:f5:nginx:1.25.3",         "created_at": "2025-01-10T09:00:00Z",         "updated_at": "2026-09-20T06:00:00Z"       },       "service": {         "id": 501,         "name": "https",         "protocol": "tcp",         "port_number": 443       },       "source": "auto",       "confidence": 90,       "is_relevant": true,       "first_seen_at": "2026-01-10T09:00:00Z",       "last_seen_at": "2026-09-20T06:00:00Z",       "created_at": "2026-01-10T09:00:00Z",       "updated_at": "2026-09-20T06:00:00Z"     }   ] }

Possible status codes

Code

Description

200

Success. Empty page if filters match nothing.

401

Unauthorized.

403

Not a member of the requested organization.


11.2 Get a Technology detection by ID

Item

Value

Method

GET

URL

/api/auth/technology-detections/{id}

Permission

Member of an organization

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

Technology detection not found or not accessible.


11.3 Export Technology detections

Item

Value

Method

GET or POST

URL

/api/auth/technology-detections/export

Permission

Member of an organization

GET exports according to the same filters as List, plus export_format. POST exports an explicit list of IDs.

Request body (JSON, POST only)

Field

Type

Required

Description

ids

array of integers

Yes

Technology detection IDs to export. At least one.

Exported columns: value, vendor, product, version, cves (CVE count), service_name, service_protocol, service_port_number, is_relevant, first_seen_at, last_seen_at.

Possible status codes

Code

Description

200

File returned.

400

POST with invalid/empty ids.

401

Unauthorized.

403

Not a member of the requested organization.

404

POST: one or more ids are not accessible.


12. CVEs

The CVE catalog cross-referenced against the Technologies detected on your assets.

12.1 List CVEs

Item

Value

Method

GET

URL

/api/auth/cves

Permission

Member of an organization

Paginated by cursor (not by page number): use the cursor query parameter from the response to fetch the next page.

Query parameters

Parameter

Type

Required

Description

after / before

date

No

Restrict to CVEs published on/after / on/before (inclusive) this date.

severity

string

No

Comma-separated severity levels as integers: 0 (info), 1 (low), 2 (medium), 3 (high), 4 (critical). Labels such as critical are rejected (400).

search

string

No

Substring match on the CVE identifier.

is_exploitable, is_in_the_news, is_in_the_wild, is_kev

boolean

No

Threat-intelligence flags.

technology_ids

string

No

Comma-separated Technology IDs.

product_ids

string

No

Comma-separated Product IDs.

vendor_ids

string

No

Comma-separated Vendor IDs.

asset_id

integer

No

Only CVEs affecting Technologies detected on this Asset ID.

related_to_org_assets

boolean

No

Only CVEs affecting at least one Technology detected on your assets.

asset_availability

string

No

Combined with related_to_org_assets: restrict to a given asset availability.

teams

string

No

Comma-separated Team IDs. Applied only when related_to_org_assets=true.

org_id

integer

No

Applied only when related_to_org_assets=true.

sorted_by

string

No

identifier, severity, cvss3_score, published_at, description.

cursor / limit

string / integer

No

Cursor pagination.

Example request

GET /api/auth/cves?severity=3,4&is_kev=true Authorization: Token <your-API-token> Accept: application/json

Example response 200 OK

{   "next": "https://dashboard.cloud.patrowl.io/api/auth/cves?cursor=cD0yMDI2LTA5LTIw",   "previous": null,   "results": [     {       "id": 55123,       "identifier": "CVE-2026-12345",       "published_at": "2026-09-15T00:00:00Z",       "description": "A stack buffer overflow in ...",       "severity": 4,       "cvss": { "score": 9.8, "version": 3 },       "threat_info": {         "is_exploitable": true,         "is_in_the_news": false,         "is_in_the_wild": true,         "is_kev": true       },       "technologies": [         { "id": 900, "product": "nginx", "version": "1.25.3", "vendor": "F5, Inc.", "partial_cpe": "cpe:2.3:a:f5:nginx:1.25.3" }       ],       "references": ["https://nvd.nist.gov/vuln/detail/CVE-2026-12345"]     }   ] }

severity is an integer: 0 (info), 1 (low), 2 (medium), 3 (high), 4 (critical), or null when no CVSS score is known yet. cvss reports the score and CVSS major version (2, 3, or 4, as an integer) of the highest CVSS version with a score (v4 > v3 > v2); null if no score is available at all.

Possible status codes

Code

Description

200

Success. Empty page if filters match nothing.

401

Unauthorized.


12.2 Retrieve a CVE by identifier

Item

Value

Method

GET

URL

/api/auth/cves/{identifier}

Permission

Member of an organization

{identifier} is the CVE identifier itself (e.g. CVE-2026-12345), not a numeric ID.

Example response 200 OK — same base fields as the list except cvss (use the per-version scores below), plus cwe, cwe_name, exploits (each with reference, notes, trust_level, tlp_level, source, availability, type, maturity, relevancy_level, published_at, modified_at), the per-version CVSS vectors/scores (cvss2_vector, cvss2_score, cvss3_vector, cvss3_score, cvss4_vector, cvss4_score), epss_score, epss_percentile, hears_score, created_at, updated_at.

Possible status codes

Code

Description

200

Success.

401

Unauthorized.

404

CVE not found.


12.3 Count CVEs

GET /api/auth/cves/count — returns {"count": <int>} for the CVEs matching the same filters as List. Permission: Member of an organization.

12.4 Count CVEs by severity

GET /api/auth/cves/by-severity — returns counts grouped by severity for the CVEs matching the List filters:

{ "info": 0, "low": 12, "medium": 34, "high": 9, "critical": 2 }

12.5 Exploitability statistics

GET /api/auth/cves/statistics — counts, among the CVEs matching the List filters, those that are potentially exploitable and those that are Known Exploited Vulnerabilities (KEV), each with a total and a count over the last week:

{   "potentially_exploitable": { "total": 15, "since_last_week": 2 },   "kev": { "total": 3, "since_last_week": 0 } }

12.6 Count CVEs by qualification

GET /api/auth/cves/by-qualification?org_id=1&related_to_org_assets=false — splits the count between your organization's own CVEs and the whole catalog, plus how many are potentially exploitable:

{ "my_cve": 8, "all": 128340, "potentially_exploitable": 15 }

12.7 Related assets count

POST /api/auth/cves/related-assets-count?org_id=1 with body {"ids": [55123, 55124]} — returns, for each requested CVE ID, the number of your assets affected:

{ "counts": [{ "id": 55123, "count": 4 }, { "id": 55124, "count": 0 }] }

Possible status codes (the four endpoints above)

Code

Description

200

Success.

400

Invalid payload/query parameters.

401

Unauthorized.


12.8 Export CVEs — updated

Item

Value

Method

GET or POST

URL

/api/auth/cves/export

Permission

Member of an organization

Same filters as List, plus export_format (csv default, or json). POST body: {"ids": [...]}.

The export shape now differs by format:

  • CSV columns: identifier, severity, cvss2_score, cvss3_score, cvss4_score, published_at, is_exploitable, is_in_the_news, is_in_the_wild, is_kev. Each CVSS version now gets its own column, instead of a single cvss3_score column.

  • JSON (export_format=json) columns: identifier, severity, cvss, published_at, is_exploitable, is_in_the_news, is_in_the_wild, is_kev. cvss mirrors the list payload's {score, version} object (the highest available CVSS version) instead of three flat score columns.

Note for existing integrations: if you parse the CSV export, the cvss3_score column is now joined by cvss2_score and cvss4_score — update column-position-based parsing to name-based parsing if you haven't already.

Possible status codes

Code

Description

200

File returned.

400

Invalid/empty ids (POST).

401

Unauthorized.


13. Asset service & topology aggregates — significantly expanded

A lightweight way to get, for a batch of assets, a set of EASM summary indicators without listing every underlying Domain/IPv4/Service record. This endpoint's response shape has grown substantially: in addition to the open-service summary, it now also returns DNS/topology aggregates (resolving domains, related subdomains, resolved IPs) and subnet-grouping information.

Item

Value

Method

POST

URL

/api/auth/assets/aggregates

Permission

Authenticated user (asset visibility applies per asset)

Request body (JSON)

Field

Type

Required

Description

asset_ids

array of integers

Yes

Asset IDs to compute aggregates for. At least one, max 500.

filters

object (string → string)

No

The same query parameters accepted by the Asset list endpoint (e.g. search, type). Narrows subnet.count so it matches an Asset list fetched with the same filters. Pagination/sorting/subnet-grouping parameters are ignored if present.

Example request

POST /api/auth/assets/aggregates Authorization: Token <your-API-token> Content-Type: application/json Accept: application/json  {   "asset_ids": [100, 101],   "filters": { "availability": "available" } }

Example response 200 OK

{   "aggregates": {     "100": {       "open_service_count": 3,       "top_service": { "name": "https", "port_number": 443 },       "resolving_domains": {         "count": 2,         "top": {           "id": 55,           "value": "www.acme.example",           "protection": { "status": "easm", "availability": "available" },           "outside_business_hours": 0         }       },       "related_subdomains": null,       "resolved_ips": null,       "subnet": {         "group_id": 9,         "cidr": "203.0.113.0/24",         "count": 14       }     },     "101": {       "open_service_count": 0,       "top_service": null,       "resolving_domains": null,       "related_subdomains": {         "count": 5,         "top": {           "id": 61,           "value": "blog.acme.example",           "protection": { "status": "unprotected", "availability": "available" },           "outside_business_hours": 0         }       },       "resolved_ips": {         "count": 1,         "top": {           "ownership": "contextualized",           "id": null,           "value": "198.51.100.7",           "protection": null,           "outside_business_hours": null         }       },       "subnet": null     }   } }

Fields, per requested asset:

Field

Description

open_service_count

Number of open Services on the asset.

top_service

The lowest-port open Service (name, port_number), or null if none.

resolving_domains

IP assets only. Count and most-recently-seen of the domain assets currently resolving to this IP (resolution seen within the last 15 days). null for non-IP assets.

related_subdomains

Domain assets only. Count and first (alphabetically) of the domain assets that are direct children of this domain. null for non-domain assets.

resolved_ips

Domain assets only. Count and most-recently-resolved of the IPv4 addresses (owned or contextualized) this domain resolves to. null for non-domain assets.

subnet

IP assets only. The most specific subnet group this IP belongs to (group_id, cidr, count — the number of your visible assets, narrowed by filters, in that same subnet). null if the IP is in no visible subnet group, or for non-IP assets.

Each topology aggregate (resolving_domains, related_subdomains, resolved_ips) follows the shape {count, top}, where top is:

  • id, value, protection: {status, availability}, outside_business_hours — for resolving_domains/related_subdomains (always a real Asset);

  • the same fields plus ownership ("owned" or "contextualized") for resolved_ips — a "contextualized" entry (a resolved IP you don't own) carries id, protection, and outside_business_hours as null, since there is no Asset behind it.

Possible status codes

Code

Description

200

Success.

400

Invalid payload (missing/empty asset_ids, invalid filters).

401

Unauthorized.


14. Breaking changes

These changes affect existing integrations and require action if you rely on the endpoints or fields below.

14.1 POST /api/auth/assets/{id}/ removed

The asset-update route no longer accepts POST. Use PATCH /api/auth/assets/{id}/ to update an existing asset; the request/response bodies are otherwise unchanged. GET /api/auth/assets/{id}/ (retrieve) is unaffected.

14.2 assets array and is_owned removed from EASM resources

The following resources no longer return an assets array (the list of assets that can see the record) or an is_owned field (whether the record belongs to your organization) in their payloads: Domains, IPv4 addresses, Services, Web servers, Certificates, Resolutions. This cross-organization data was removed from EASM responses. If you relied on is_owned to distinguish your own assets from third-party/contextual ones, use the resource-specific ownership filter instead where available (e.g. is_owned as a query parameter on GET /api/auth/ipv4s still works — only the response field was removed).

14.3 state field removed from Resolutions

easm.Resolution no longer exposes a state field, and the ?state= filter, the corresponding sort option, and the export column have all been removed. This field only ever returned active and carried no useful information. Use the new resolves boolean field instead (true if the resolution has been observed within the last 15 days). Also note the 90-day visibility window described in §3: resolutions not re-observed in that window stop being returned by the API entirely.

14.4 Domain.expiration_date renamed to expiration_dates

The WHOIS expiration field on GET /api/auth/domains is now named expiration_dates (plural, consistent with the other WHOIS array fields creation_dates/updated_dates). Update any integration reading expiration_date.

14.5 CVE CSV export columns changed

The CSV export of GET/POST /api/auth/cves/export now has three CVSS score columns (cvss2_score, cvss3_score, cvss4_score) instead of one (cvss3_score) — see §12.8. If you parse this CSV by column position rather than by header name, this is a breaking change.


15. Common error response format

Validation and permission errors are generally returned as a JSON body:

{   "detail": "Human-readable description of the error." }

or, for field-specific validation errors:

{   "<field_name>": "Human-readable description of the error." }

HTTP status codes used across this document:

Code

Usage

200

Success (including exports).

400

Bad request (invalid/missing parameters or body).

401

Unauthorized (missing/invalid token).

403

Forbidden (not a member of the requested organization).

404

Not found (resource does not exist, or is outside your visible scope).


16. Summary table

Resource

List

Retrieve

Export (GET/POST)

Domains

GET /api/auth/domains

GET /api/auth/domains/{id}

/api/auth/domains/export

IPv4 addresses

GET /api/auth/ipv4s

GET /api/auth/ipv4s/{id}

/api/auth/ipv4s/export

Resolutions

GET /api/auth/resolutions

GET /api/auth/resolutions/{id}

/api/auth/resolutions/export

ASNs

GET /api/auth/asns

GET /api/auth/asns/{id}

/api/auth/asns/export

Services

GET /api/auth/services

GET /api/auth/services/{id}

/api/auth/services/export

Web servers

GET /api/auth/webservers

GET /api/auth/webservers/{id}

/api/auth/webservers/export

Certificates

GET /api/auth/certificates

GET /api/auth/certificates/{id}

/api/auth/certificates/export

Vendors

GET /api/auth/vendors

GET /api/auth/vendors/{id}

/api/auth/vendors/export

Products

GET /api/auth/products

GET /api/auth/products/{id}

/api/auth/products/export

Technologies

GET /api/auth/technologies

GET /api/auth/technologies/{id}

/api/auth/technologies/export (+ POST .../technologies/aggregates)

Technology detections (new)

GET /api/auth/technology-detections

GET /api/auth/technology-detections/{id}

/api/auth/technology-detections/export

CVEs

GET /api/auth/cves

GET /api/auth/cves/{identifier}

/api/auth/cves/export (+ count, by-severity, statistics, by-qualification, related-assets-count)

Asset aggregates

—

—

POST /api/auth/assets/aggregates

Removed: POST /api/auth/assets/{id}/ (use PATCH instead, see §14.1).

New in this release: the Technology detections resource (§11); the resolving_domains, related_subdomains, resolved_ips, and subnet fields on POST /api/auth/assets/aggregates (§13); per-version CVSS columns on the CVE CSV export (§12.8).

Did this answer your question?