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 |
| integer | Restrict results to one of your organizations. Defaults to all organizations you belong to. |
| string | Comma-separated Asset IDs. Restrict results to resources owned through these assets. |
| string | Comma-separated protections (e.g. |
| integer | Restrict results to assets with this outside-business-hours setting. |
| 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 |
|
URL |
|
Permission | Member of an organization |
Paginated with page numbers (count/next/previous/results).
Query parameters
Parameter | Type | Required | Description |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated Domain IDs. |
| string | No | Case-insensitive search on the domain name. |
| boolean | No |
|
| integer | No | Only the direct subdomains of this Domain ID. |
| integer | No | Only the direct subdomains of the Domain owned by this Asset ID. |
| integer | No | Only the subdomains belonging to this apex Domain ID. |
| integer | No | Only the Domains currently resolving to this IPv4 ID (resolution seen in the last 90 days). |
| string | No |
|
| 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 |
|
URL |
|
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 |
|
URL |
|
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 |
| array of integers | Yes | Domain IDs to export. At least one. |
Possible status codes
Code | Description |
200 | File returned. |
400 | Invalid/empty |
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 |
|
URL |
|
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 |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated IPv4 IDs. |
| string | No | Text search on the IP value. |
| string | No | Exact IPv4 address. |
| string | No | IP type: |
| boolean | No | Only IPs present on a blocklist. |
| integer | No | Filter by ASN ID. |
| boolean | No |
|
| integer | No | Only IPs resolved from the Domain owned by this Asset ID. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
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 |
| array of integers | Yes | IPv4 IDs to export. |
Possible status codes
Code | Description |
200 | File returned. |
400 | POST with invalid/empty |
401 | Unauthorized. |
403 | Caller is not a member of the requested organization. |
404 | POST: one or more |
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 |
|
URL |
|
Permission | Member of an organization |
Query parameters
Parameter | Type | Required | Description |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated resolution IDs. |
| string | No | Text search on the domain or IPv4 value. |
| integer | No | Filter by Domain ID. |
| integer | No | Filter by IPv4 ID. |
| string | No | Exact domain value (case-insensitive). |
| string | No | Exact IPv4 address. |
| boolean | No |
|
| datetime | No | First observed on/after or on/before this date. |
| datetime | No | Last observed on/after or on/before this date. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
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 |
| array of integers | Yes | Resolution IDs to export. |
Possible status codes
Code | Description |
200 | File returned. |
400 | POST with invalid/empty |
401 | Unauthorized. |
403 | Caller is not a member of the requested organization. |
404 | POST: one or more |
4. ASNs
Autonomous systems (ASN) associated with your assets' IPv4 addresses.
4.1 List ASNs
Item | Value |
Method |
|
URL |
|
Permission | Member of an organization |
Query parameters
Parameter | Type | Required | Description |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated ASN IDs. |
| string | No | Text search on the number, description, CIDR, or registry. |
| string | No | ASN number, plain ( |
| string | No | Partial (contains) match on the CIDR block. |
| string | No | Exact registry (e.g. |
| string | No | Exact country code, case-insensitive. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
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 |
| array of integers | Yes | ASN IDs to export. |
Possible status codes
Code | Description |
200 | File returned. |
400 | POST with invalid/empty |
401 | Unauthorized. |
403 | Caller is not a member of the requested organization. |
404 | POST: one or more |
5. Services
Network services (open ports) detected on scanned assets.
5.1 List Services
Item | Value |
Method |
|
URL |
|
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 |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated Service IDs. |
| string | No | Searches the service name, the banner text, and the port number. |
| integer | No | Only Services exposing this WebServer ID. |
| boolean | No | Only Services with (or without) a TLS certificate. |
| string | No | Comma-separated Certificate IDs. |
| string | No | Comma-separated Technology IDs detected on the service. |
| string | No | Asset type of the underlying asset: |
| string | No |
|
| string | No |
|
| string | No | Comma-separated asset availability values. |
| boolean | No | Only services using TLS. |
| integer | No | Exact port number. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
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 |
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 |
|
URL |
|
Permission | Member of an organization |
Query parameters
Parameter | Type | Required | Description |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated Web server IDs. |
| string | No | Text search on the asset value, URL, title, path, and server. |
| string | No | Exact asset value (case-insensitive). |
| string | No | Exact URL (case-insensitive). |
| string | No | Exact filter on the server header. |
| string | No | Exact filter on the page title. |
| string | No | Exact filter on the JARM fingerprint. |
| integer | No | Exact filter on the returned HTTP status code. |
| integer | No | Filter on the associated Service ID. |
| boolean | No | Filter on whether the underlying Service uses SSL. |
| string | No | Filter on the underlying Service's state ( |
| integer | No | Restrict to Web servers belonging to this Asset. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
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 |
| array of integers | Yes | Web server IDs to export. |
Possible status codes
Code | Description |
200 | File returned. |
400 | POST with invalid/empty |
401 | Unauthorized. |
403 | Caller is not a member of the requested organization. |
404 | POST: one or more |
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 |
|
URL |
|
Permission | Member of an organization |
Query parameters
Parameter | Type | Required | Description |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated Certificate IDs. |
| string | No | Searches the serial number, the raw certificate text, and the value of the assets presenting it. |
| string | No | Exact match on the serial number (colon-insensitive and case-insensitive). |
| boolean | No | Filter expired / non-expired certificates. |
| boolean | No | Filter certificates whose name doesn't match the domain. |
| boolean | No | Filter self-signed certificates. |
| string | No | Exact (case-insensitive) match on the value of an asset presenting the certificate. |
| integer | No | Filter by the port of a service presenting the certificate. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
Permission | Member of an organization |
Request body (JSON, POST only)
Field | Type | Required | Description |
| array of integers | Yes | Certificate IDs to export. At least one. |
Possible status codes
Code | Description |
200 | File returned. |
400 | POST with invalid/empty |
401 | Unauthorized. |
403 | Not a member of any organization. |
404 | One or more requested |
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 |
|
URL |
|
Permission | Member of an organization |
Query parameters
Parameter | Type | Required | Description |
| string | No | Comma-separated Vendor IDs. |
| string | No | Case-insensitive search on the vendor name. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
Permission | Member of an organization |
Request body (JSON, POST only)
Field | Type | Required | Description |
| array of integers | Yes | Vendor IDs to export. At least one. |
Possible status codes
Code | Description |
200 | File returned. |
400 | POST with invalid/empty |
401 | Unauthorized. |
403 | Not a member of any organization. |
404 | One or more requested |
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 |
|
URL |
|
Permission | Member of an organization |
Query parameters
Parameter | Type | Required | Description |
| string | No | Comma-separated Product IDs. |
| string | No | Case-insensitive search on the product name or its vendor's name. |
| string | No | Comma-separated Vendor IDs. Restrict to products of these vendors. |
| string | No | Product type: |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
Permission | Member of an organization |
Request body (JSON, POST only)
Field | Type | Required | Description |
| array of integers | Yes | Product IDs to export. At least one. |
Possible status codes
Code | Description |
200 | File returned. |
400 | POST with invalid/empty |
401 | Unauthorized. |
403 | Not a member of any organization. |
404 | One or more requested |
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 |
|
URL |
|
Permission | Member of an organization |
Query parameters
Parameter | Type | Required | Description |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated Product IDs. |
| string | No | Comma-separated Vendor IDs. |
| string | No | Case-insensitive substring match on the detected version. |
| string | No | Product category (see the Products resource). |
| boolean | No | Only Technologies with at least one detection flagged as relevant/irrelevant. |
| string | No | Only Technologies with a detection from this source: |
| string | No | Matches product name, vendor name, or version (space-separated terms, AND across words). |
| integer | No | Only the Technologies detected on this Asset ID. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
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 |
| 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 |
401 | Unauthorized. |
10.4 Export Technologies
GET exports according to the same filters as List; POST exports only the given IDs.
Item | Value |
Method |
|
URL |
|
Permission | Member of an organization |
Possible status codes
Code | Description |
200 | File returned. |
400 | Invalid/empty |
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 |
|
URL |
|
Permission | Member of an organization |
Query parameters
Parameter | Type | Required | Description |
| — | No | See base scoping parameters above. |
| string | No | Comma-separated Technology detection IDs. |
| string | No | Comma-separated Technology IDs. |
| string | No | Comma-separated Product IDs. |
| string | No | Comma-separated Vendor IDs. |
| string | No | Comma-separated Service IDs. |
| string | No | Case-insensitive substring match on the detected version. |
| boolean | No | Only detections flagged as relevant (or irrelevant). |
| string | No | Only detections from this source: |
| string | No | Matches the asset value, vendor name, product name, version, or service name (space-separated terms, AND across words). |
| datetime | No | First seen on/after or on/before this date. |
| datetime | No | Last seen on/after or on/before this date. |
| string | No |
|
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 |
|
URL |
|
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 |
|
URL |
|
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 |
| 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 |
401 | Unauthorized. |
403 | Not a member of the requested organization. |
404 | POST: one or more |
12. CVEs
The CVE catalog cross-referenced against the Technologies detected on your assets.
12.1 List CVEs
Item | Value |
Method |
|
URL |
|
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 |
| date | No | Restrict to CVEs published on/after / on/before (inclusive) this date. |
| string | No | Comma-separated severity levels as integers: |
| string | No | Substring match on the CVE identifier. |
| boolean | No | Threat-intelligence flags. |
| string | No | Comma-separated Technology IDs. |
| string | No | Comma-separated Product IDs. |
| string | No | Comma-separated Vendor IDs. |
| integer | No | Only CVEs affecting Technologies detected on this Asset ID. |
| boolean | No | Only CVEs affecting at least one Technology detected on your assets. |
| string | No | Combined with |
| string | No | Comma-separated Team IDs. Applied only when |
| integer | No | Applied only when |
| string | No |
|
| 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 |
|
URL |
|
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 |
|
URL |
|
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 singlecvss3_scorecolumn.JSON (
export_format=json) columns:identifier,severity,cvss,published_at,is_exploitable,is_in_the_news,is_in_the_wild,is_kev.cvssmirrors 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 |
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 |
|
URL |
|
Permission | Authenticated user (asset visibility applies per asset) |
Request body (JSON)
Field | Type | Required | Description |
| array of integers | Yes | Asset IDs to compute aggregates for. At least one, max 500. |
| object (string → string) | No | The same query parameters accepted by the Asset list endpoint (e.g. |
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 |
| Number of open Services on the asset. |
| The lowest-port open Service ( |
| IP assets only. Count and most-recently-seen of the domain assets currently resolving to this IP (resolution seen within the last 15 days). |
| Domain assets only. Count and first (alphabetically) of the domain assets that are direct children of this domain. |
| Domain assets only. Count and most-recently-resolved of the IPv4 addresses (owned or contextualized) this domain resolves to. |
| IP assets only. The most specific subnet group this IP belongs to ( |
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— forresolving_domains/related_subdomains(always a real Asset);the same fields plus
ownership("owned"or"contextualized") forresolved_ips— a"contextualized"entry (a resolved IP you don't own) carriesid,protection, andoutside_business_hoursasnull, since there is no Asset behind it.
Possible status codes
Code | Description |
200 | Success. |
400 | Invalid payload (missing/empty |
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 |
|
|
|
IPv4 addresses |
|
|
|
Resolutions |
|
|
|
ASNs |
|
|
|
Services |
|
|
|
Web servers |
|
|
|
Certificates |
|
|
|
Vendors |
|
|
|
Products |
|
|
|
Technologies |
|
|
|
Technology detections (new) |
|
|
|
CVEs |
|
|
|
Asset 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).
