Getting started
Overview¶
This guide explains how to manage DNS Protection configuration through the dns-protection/v2 API.
The V2 API is centered around three main resource types:
- Locations: Where DNS traffic originates from. A location can contain IP addresses, domain names, DNS over HTTPS settings, and an optional policy assignment.
- Policies: How DNS traffic should be handled. A policy can reference locations, web-category actions, rejected web categories, safe search settings, and optional custom domains lists.
- Custom Domains Lists: Reusable groups of domains that policies can reference for either allow or block treatment. A custom domains list contains a name, an optional description, and a set of domain names.
In practical terms, most integrations follow this order:
- Create or list the locations you want to manage.
- Optionally create one or more custom domains lists to allow or block specific domains.
- Create a policy that references the location IDs and any custom domains list IDs you want to apply.
- Update the policy and its referenced lists over time as your filtering requirements change.
Pre-requisites¶
You must be enrolled in the Sophos Partner Program to call this API as a partner. You must read the Partner Getting started guide first.
To call this API for an organization that has Sophos Fusion Enterprise access enabled, read the Organization Getting started guide.
If neither profile fits you, read the Tenant Getting started guide.
The examples in this guide assume that you already have:
- a valid JWT access token:
{jwt} - the tenant UUID you want to manage:
{tenantId} - the regional API hostname for the tenant's data region
If you use tenant credentials, you can get the tenant UUID from the Who-am-I API. If you use partner or organization credentials, use the relevant tenant-listing API to discover the tenant UUID first.
Base path and common headers¶
Base path¶
/dns-protection/v2
Common headers¶
Authorization: Bearer {jwt}
X-Tenant-ID: {tenantId}
Accept: application/json
Content-Type: application/json
Pagination behavior¶
The paginated V2 endpoints use the same pagination model:
pageis 1-basedpage=0returns page metadata only and no itemspageSizedefaults to20- the maximum supported
pageSizeis200 pageTotal=trueincludes total page and item counts in the response
How the resources fit together¶
The DNS Protection V2 resources are related in the following way:
- A policy can reference one or more location IDs through
locationIds. - A location can be assigned to only one DNS Protection policy at a time.
- A policy can optionally reference custom domains list IDs through
allowedCustomDomainIdsandblockedCustomDomainIds. - A custom domains list is an independent resource that can be referenced by zero or more policies, and the same list cannot appear in both the allowed and blocked sets of a single policy.
- When you retrieve a location, the response can include
policyIdso you can see which policy currently owns it.
This means you typically use the APIs together:
- Use
/locationsto create or discover the locations you want to protect. - Use
/custom-domainsto create the allow or block lists you want to apply. - Use
/policiesto define filtering behavior for those locations and to reference your custom domains lists.
Locations API¶
You can use the Locations API to create, list, update, and delete DNS Protection locations.
| Operation | HTTP Method | Path | Description |
|---|---|---|---|
| Create location | POST | /locations | Creates a new location |
| List locations | GET | /locations | Returns a paginated list of locations |
| Get location by ID | GET | /locations/{id} | Returns one location |
| Update location | PATCH | /locations/{id} | Partially updates a location |
| Delete location | DELETE | /locations/{id} | Deletes a location |
Location types¶
DNS Protection locations are of type standard. The type field is case-sensitive and must be supplied in lowercase. If you omit type when creating a location, it defaults to standard.
Important behavior:
- The default location is auto-provisioned for the tenant on first list of locations and cannot be deleted.
- A location is hard-deleted when you call
DELETE /locations/{id}.
Location fields¶
| Field | Type | Notes |
|---|---|---|
id | UUID (read-only) | Server-assigned identifier |
name | string | Required. 1–100 chars, alphanumeric, space, -, _ |
description | string | Optional. Up to 250 chars |
type | string | Currently only standard is supported. Case-sensitive and must be lowercase. Defaults to standard |
label | string | Optional. Up to 256 chars. Always returned in responses, even when not supplied |
isDefault | boolean | Whether this is the tenant's default location |
ipAddresses | string set | IPv4 and/or IPv6 addresses |
domainNames | string set | Fully-qualified domain names |
dohEnabled | boolean | Whether DNS over HTTPS is enabled |
dohSecureLocationId | string (read-only) | Globally unique ID generated for DoH locations |
dohUrl | string (read-only) | The full DoH endpoint URL |
policyId | UUID | The policy currently assigned to this location, if any |
createdAt | date-time (read-only) | Creation timestamp |
updatedAt | date-time (read-only) | Last update timestamp |
The combined number of items in ipAddresses and domainNames cannot exceed 100.
Create location¶
Use this endpoint to create a location that can later be assigned to a policy.
Request
POST /dns-protection/v2/locations
X-Tenant-ID: {tenantId}
Content-Type: application/json
{
"name": "Headquarters",
"description": "Primary office egress location",
"type": "standard",
"dohEnabled": true,
"ipAddresses": ["203.0.113.10"],
"domainNames": ["office.example.com"]
}
Response
- Status:
201 Created
{
"id": "0a13c4cd-4db9-4e53-af5b-06827c347b71",
"name": "Headquarters",
"description": "Primary office egress location",
"type": "standard",
"label": "Headquarters",
"isDefault": false,
"ipAddresses": ["203.0.113.10"],
"domainNames": ["office.example.com"],
"dohEnabled": true,
"dohSecureLocationId": "392oj0e54880r",
"dohUrl": "https://392oj0e54880r.secure.dnsprotection.sophos.com/dns-query",
"createdAt": "2026-04-23T10:15:30.000Z",
"updatedAt": "2026-04-23T10:15:30.000Z"
}
Notes
- The combined number of
ipAddressesanddomainNamesmust not exceed100. nameis required, 1–100 characters, and must be unique within the tenant. Allowed characters are alphanumeric, space,-, and_.- If you want the location to act as the tenant default, use a
standardlocation and setisDefaulttotrue. Only one default location can exist per tenant. - If you omit
type, the location is created asstandard.
List locations¶
Use this endpoint to retrieve locations, optionally filtered and sorted.
Request
GET /dns-protection/v2/locations?page=1&pageSize=20&pageTotal=true
X-Tenant-ID: {tenantId}
Supported query parameters
Pagination
page: page number to fetch, starting at1pageSize: number of items to returnpageTotal: whether to include total page and item counts
Filtering
name: exact location namenameContains: partial location name matchisDefault:trueorfalse(case-insensitive)ipAddressesContains: comma-separated list of IP addresses; matches locations whose addresses contain any of the given valuesdomainNames: comma-separated list of exact domain names to match
Sorting
sort: one or more ofname,description, ordohEnabled- Format:
fieldorfield:ascorfield:desc - Multiple fields are comma-separated, up to
3fields per request
Response
- Status:
200 OK
{
"pages": {
"current": 1,
"size": 20,
"total": 1,
"items": 2,
"maxSize": 200
},
"items": [
{
"id": "0a13c4cd-4db9-4e53-af5b-06827c347b71",
"name": "Headquarters",
"description": "Primary office egress location",
"type": "standard",
"label": "Headquarters",
"isDefault": false,
"ipAddresses": ["203.0.113.10"],
"domainNames": ["office.example.com"],
"dohEnabled": true,
"policyId": "1f9a42c0-b5ff-49b8-9a2d-2cc161cb9e52",
"createdAt": "2026-04-23T10:15:30.000Z",
"updatedAt": "2026-04-23T10:20:00.000Z"
},
{
"id": "06d83935-bfb2-49a9-aadc-7563d92608b9",
"name": "Default",
"description": "Provided to simplify setup of endpoint integration with DNS Protection.",
"type": "standard",
"label": "Default Location",
"isDefault": true,
"dohEnabled": true,
"createdAt": "2026-04-20T08:00:00.000Z",
"updatedAt": "2026-04-20T08:00:00.000Z"
}
]
}
Filtering examples
Filter by exact name:
GET /dns-protection/v2/locations?name=Headquarters
X-Tenant-ID: {tenantId}
Filter by partial name:
GET /dns-protection/v2/locations?nameContains=Office
X-Tenant-ID: {tenantId}
Filter by default flag and IP address:
GET /dns-protection/v2/locations?isDefault=false&ipAddressesContains=203.0.113.10
X-Tenant-ID: {tenantId}
Filter by exact domain names:
GET /dns-protection/v2/locations?domainNames=office.example.com,branch.example.com
X-Tenant-ID: {tenantId}
Sort by name, then description descending:
GET /dns-protection/v2/locations?sort=name,description:desc
X-Tenant-ID: {tenantId}
Get location by ID¶
Use this endpoint to retrieve a single location.
Request
GET /dns-protection/v2/locations/{id}
X-Tenant-ID: {tenantId}
Response
- Status:
200 OK
{
"id": "0a13c4cd-4db9-4e53-af5b-06827c347b71",
"name": "Headquarters",
"description": "Primary office egress location",
"type": "standard",
"label": "Headquarters",
"isDefault": false,
"ipAddresses": ["203.0.113.10"],
"domainNames": ["office.example.com"],
"dohEnabled": true,
"policyId": "1f9a42c0-b5ff-49b8-9a2d-2cc161cb9e52",
"dohSecureLocationId": "392oj0e54880r",
"dohUrl": "https://392oj0e54880r.secure.dnsprotection.sophos.com/dns-query",
"createdAt": "2026-04-23T10:15:30.000Z",
"updatedAt": "2026-04-23T10:20:00.000Z"
}
Update location¶
Use PATCH to update only the fields you want to change.
For ipAddresses and domainNames, you can:
- send a full array to replace the existing values
- send an object with
addandremovefor partial changes - send
nullto clear the field
Request
PATCH /dns-protection/v2/locations/{id}
X-Tenant-ID: {tenantId}
Content-Type: application/json
{
"description": "Primary office location for EMEA users",
"domainNames": {
"add": ["branch.example.com"],
"remove": ["office.example.com"]
},
"dohEnabled": false
}
Response
- Status:
200 OK
{
"id": "0a13c4cd-4db9-4e53-af5b-06827c347b71",
"name": "Headquarters",
"description": "Primary office location for EMEA users",
"type": "standard",
"label": "Headquarters",
"isDefault": false,
"ipAddresses": ["203.0.113.10"],
"domainNames": ["branch.example.com"],
"dohEnabled": false,
"createdAt": "2026-04-23T10:15:30.000Z",
"updatedAt": "2026-04-23T11:05:00.000Z"
}
Delete location¶
Use this endpoint to delete a location.
Request
DELETE /dns-protection/v2/locations/{id}
X-Tenant-ID: {tenantId}
Response
- Status:
200 OK
{
"deleted": true
}
Policies API¶
You can use the Policies API to create, list, update, and delete DNS Protection policies.
| Operation | HTTP Method | Path | Description |
|---|---|---|---|
| Create policy | POST | /policies | Creates a new policy |
| List policies | GET | /policies | Returns a paginated list of policies |
| Get policy by ID | GET | /policies/{id} | Returns one policy |
| Update policy | PATCH | /policies/{id} | Partially updates a policy |
| Delete policy | DELETE | /policies/{id} | Deletes a policy |
Policy fields¶
The main policy fields are:
| Field | Type | Notes |
|---|---|---|
id | UUID (read-only) | Server-assigned identifier |
name | string | Required. 1–100 chars, unique within the tenant. Alphanumeric, space, -, _ |
description | string | Optional. Up to 250 chars |
categoryPolicy | string | One of clean, optimal, bandwidth, business, or custom. Defaults to clean |
categoryGroupActionSettings | object | Required on create. Map of category-group key to action. See below |
rejectedWebCategories | integer set | Required on create. Web category IDs to reject. Each value must be in the range 1–110 |
locationIds | UUID set | Required on create. The locations this policy applies to. Up to 100 IDs |
customDomainsEnabled | boolean | Whether the allowed and blocked custom domains lists should be applied |
allowedCustomDomainIds | UUID set | UUIDs of custom domains lists allowed by this policy. Up to 100 |
blockedCustomDomainIds | UUID set | UUIDs of custom domains lists blocked by this policy. Up to 100 |
safeSearchForSearchEnginesEnabled | boolean | Safe search flag for search engines |
safeSearchForYouTubeEnabled | boolean | Safe search flag for YouTube |
safeSearchYouTubeRestrictionLevel | string | moderate or strict |
createdAt | date-time (read-only) | Creation timestamp |
updatedAt | date-time (read-only) | Last update timestamp |
The action value for each entry in categoryGroupActionSettings must be one of allow, block, or alert.
When you create a policy, categoryGroupActionSettings must include all of the following keys, each mapped to a valid action:
adultsocialthreatsbusinessdatalossbandwidthproductivityuncategorizedinfrastructure
Omitting any of these keys on create causes the request to be rejected.
Create policy¶
Use this endpoint to create a new DNS Protection policy.
Request
POST /dns-protection/v2/policies
X-Tenant-ID: {tenantId}
Content-Type: application/json
{
"name": "Office Policy",
"description": "Baseline browsing policy for office users",
"categoryPolicy": "optimal",
"categoryGroupActionSettings": {
"adult": "block",
"social": "allow",
"threats": "block",
"business": "allow",
"dataloss": "block",
"bandwidth": "allow",
"productivity": "allow",
"uncategorized": "allow",
"infrastructure": "allow"
},
"rejectedWebCategories": [17, 42],
"locationIds": [
"0a13c4cd-4db9-4e53-af5b-06827c347b71"
],
"customDomainsEnabled": true,
"allowedCustomDomainIds": [
"7a1ec1af-3b8d-47ad-bf91-ff05e9b94d28"
],
"blockedCustomDomainIds": [
"fe5d3f11-f8a5-45c3-b5be-48e0b66d15d2"
],
"safeSearchForSearchEnginesEnabled": true,
"safeSearchForYouTubeEnabled": true,
"safeSearchYouTubeRestrictionLevel": "strict"
}
Response
- Status:
201 Created
{
"id": "1f9a42c0-b5ff-49b8-9a2d-2cc161cb9e52",
"name": "Office Policy",
"description": "Baseline browsing policy for office users",
"categoryPolicy": "optimal",
"categoryGroupActionSettings": {
"adult": "block",
"social": "allow",
"threats": "block",
"business": "allow",
"dataloss": "block",
"bandwidth": "allow",
"productivity": "allow",
"uncategorized": "allow",
"infrastructure": "allow"
},
"rejectedWebCategories": [17, 42],
"locationIds": [
"0a13c4cd-4db9-4e53-af5b-06827c347b71"
],
"customDomainsEnabled": true,
"allowedCustomDomainIds": [
"7a1ec1af-3b8d-47ad-bf91-ff05e9b94d28"
],
"blockedCustomDomainIds": [
"fe5d3f11-f8a5-45c3-b5be-48e0b66d15d2"
],
"safeSearchForSearchEnginesEnabled": true,
"safeSearchForYouTubeEnabled": true,
"safeSearchYouTubeRestrictionLevel": "strict",
"createdAt": "2026-04-23T12:00:00.000Z",
"updatedAt": "2026-04-23T12:00:00.000Z"
}
Notes
name,categoryGroupActionSettings,rejectedWebCategories, andlocationIdsare required to create a policy.categoryGroupActionSettingsmust include every category-group key listed above; omitting any of them causes a400 Bad Request.locationIdsmust reference existing DNS Protection locations, and a location can only belong to one policy at a time.allowedCustomDomainIdsandblockedCustomDomainIdsmust reference existing custom domains lists and must not contain overlapping IDs.- Each value in
rejectedWebCategoriesmust be an integer in the range1–110.
List policies¶
Use this endpoint to retrieve policies, optionally filtered and sorted.
Request
GET /dns-protection/v2/policies?page=1&pageSize=20&pageTotal=true
X-Tenant-ID: {tenantId}
Supported query parameters
Pagination
pagepageSizepageTotal
Filtering
name: exact policy namenameContains: partial policy name matchcategoryPolicy:clean,optimal,bandwidth,business, orcustom(case-insensitive)safeSearchYouTubeRestrictionLevel:moderateorstrict(case-insensitive)safeSearchForSearchEnginesEnabled:trueorfalsesafeSearchForYouTubeEnabled:trueorfalse
Sorting
sort: one or more ofname,description,categoryPolicy,createdAt,updatedAt- Format:
fieldorfield:ascorfield:desc - Multiple fields are comma-separated, up to
5fields per request
Response
- Status:
200 OK
{
"pages": {
"current": 1,
"size": 20,
"total": 1,
"items": 1,
"maxSize": 200
},
"items": [
{
"id": "1f9a42c0-b5ff-49b8-9a2d-2cc161cb9e52",
"name": "Office Policy",
"description": "Baseline browsing policy for office users",
"categoryPolicy": "optimal",
"categoryGroupActionSettings": {
"adult": "block",
"social": "allow",
"threats": "block",
"business": "allow",
"dataloss": "block",
"bandwidth": "allow",
"productivity": "allow",
"uncategorized": "allow",
"infrastructure": "allow"
},
"rejectedWebCategories": [17, 42],
"locationIds": [
"0a13c4cd-4db9-4e53-af5b-06827c347b71"
],
"customDomainsEnabled": true,
"allowedCustomDomainIds": [
"7a1ec1af-3b8d-47ad-bf91-ff05e9b94d28"
],
"blockedCustomDomainIds": [
"fe5d3f11-f8a5-45c3-b5be-48e0b66d15d2"
],
"safeSearchForSearchEnginesEnabled": true,
"safeSearchForYouTubeEnabled": true,
"safeSearchYouTubeRestrictionLevel": "strict",
"createdAt": "2026-04-23T12:00:00.000Z",
"updatedAt": "2026-04-23T12:00:00.000Z"
}
]
}
Filtering examples
Filter by exact name:
GET /dns-protection/v2/policies?name=Office%20Policy
X-Tenant-ID: {tenantId}
Filter by partial name:
GET /dns-protection/v2/policies?nameContains=Office
X-Tenant-ID: {tenantId}
Filter by category policy:
GET /dns-protection/v2/policies?categoryPolicy=optimal
X-Tenant-ID: {tenantId}
Filter by safe search settings:
GET /dns-protection/v2/policies?safeSearchForSearchEnginesEnabled=true&safeSearchForYouTubeEnabled=true
X-Tenant-ID: {tenantId}
Sort by name, then newest update first:
GET /dns-protection/v2/policies?sort=name,updatedAt:desc
X-Tenant-ID: {tenantId}
Get policy by ID¶
Use this endpoint to retrieve a single policy.
Request
GET /dns-protection/v2/policies/{id}
X-Tenant-ID: {tenantId}
Response
- Status:
200 OK
{
"id": "1f9a42c0-b5ff-49b8-9a2d-2cc161cb9e52",
"name": "Office Policy",
"description": "Baseline browsing policy for office users",
"categoryPolicy": "optimal",
"categoryGroupActionSettings": {
"adult": "block",
"social": "allow",
"threats": "block",
"business": "allow",
"dataloss": "block",
"bandwidth": "allow",
"productivity": "allow",
"uncategorized": "allow",
"infrastructure": "allow"
},
"rejectedWebCategories": [17, 42],
"locationIds": [
"0a13c4cd-4db9-4e53-af5b-06827c347b71"
],
"customDomainsEnabled": true,
"allowedCustomDomainIds": [
"7a1ec1af-3b8d-47ad-bf91-ff05e9b94d28"
],
"blockedCustomDomainIds": [
"fe5d3f11-f8a5-45c3-b5be-48e0b66d15d2"
],
"safeSearchForSearchEnginesEnabled": true,
"safeSearchForYouTubeEnabled": true,
"safeSearchYouTubeRestrictionLevel": "strict",
"createdAt": "2026-04-23T12:00:00.000Z",
"updatedAt": "2026-04-23T12:00:00.000Z"
}
Update policy¶
Use PATCH to update only the fields you want to change.
For the set-style fields below, you have two supported patterns:
- send a full array to replace the existing values
- send an object with
addandremoveto update incrementally
This applies to:
locationIdsallowedCustomDomainIdsblockedCustomDomainIdsrejectedWebCategories
If you want to clear one of those fields completely, send an empty array.
Request
PATCH /dns-protection/v2/policies/{id}
X-Tenant-ID: {tenantId}
Content-Type: application/json
{
"description": "Updated browsing policy for office users",
"locationIds": {
"add": ["16d0872f-7ec3-4d81-a88e-1b7b79a89f8d"],
"remove": ["0a13c4cd-4db9-4e53-af5b-06827c347b71"]
},
"blockedCustomDomainIds": [],
"safeSearchForSearchEnginesEnabled": true,
"safeSearchForYouTubeEnabled": true,
"safeSearchYouTubeRestrictionLevel": "strict"
}
Response
- Status:
200 OK
{
"id": "1f9a42c0-b5ff-49b8-9a2d-2cc161cb9e52",
"name": "Office Policy",
"description": "Updated browsing policy for office users",
"categoryPolicy": "optimal",
"categoryGroupActionSettings": {
"adult": "block",
"social": "allow",
"threats": "block",
"business": "allow",
"dataloss": "block",
"bandwidth": "allow",
"productivity": "allow",
"uncategorized": "allow",
"infrastructure": "allow"
},
"rejectedWebCategories": [17, 42],
"locationIds": [
"16d0872f-7ec3-4d81-a88e-1b7b79a89f8d"
],
"customDomainsEnabled": true,
"allowedCustomDomainIds": [
"7a1ec1af-3b8d-47ad-bf91-ff05e9b94d28"
],
"blockedCustomDomainIds": [],
"safeSearchForSearchEnginesEnabled": true,
"safeSearchForYouTubeEnabled": true,
"safeSearchYouTubeRestrictionLevel": "strict",
"createdAt": "2026-04-23T12:00:00.000Z",
"updatedAt": "2026-04-23T12:30:00.000Z"
}
Delete policy¶
Use this endpoint to delete a policy.
Request
DELETE /dns-protection/v2/policies/{id}
X-Tenant-ID: {tenantId}
Response
- Status:
200 OK
{
"deleted": true
}
Deleting a policy removes the policy record and unassigns its locations.
Custom Domains Lists API¶
You can use the Custom Domains Lists API to create, list, update, and delete reusable lists of domains that policies can reference through allowedCustomDomainIds and blockedCustomDomainIds.
| Operation | HTTP Method | Path | Description |
|---|---|---|---|
| Create custom domains list | POST | /custom-domains | Creates a new custom domains list |
| List custom domains lists | GET | /custom-domains | Returns a paginated list of custom domains lists |
| Get custom domains list by ID | GET | /custom-domains/{id} | Returns one custom domains list |
| Update custom domains list | PATCH | /custom-domains/{id} | Partially updates a custom domains list |
| Delete custom domains list | DELETE | /custom-domains/{id} | Deletes a custom domains list |
Custom domains list fields¶
The main fields are:
name: unique custom domains list name within the tenantdescription: optional descriptiondomains: set of domain names that belong to the listid: server-assigned UUID (read-only)createdAt: timestamp when the list was created (read-only)updatedAt: timestamp when the list was last updated (read-only)
Create custom domains list¶
Use this endpoint to create a custom domains list that policies can later reference.
Request
POST /dns-protection/v2/custom-domains
X-Tenant-ID: {tenantId}
Content-Type: application/json
{
"name": "Blocked Sites",
"description": "Domains we always want to block for office users",
"domains": [
"malware.example.com",
"phishing.example.com"
]
}
Response
- Status:
201 Created
{
"id": "fe5d3f11-f8a5-45c3-b5be-48e0b66d15d2",
"name": "Blocked Sites",
"description": "Domains we always want to block for office users",
"domains": [
"malware.example.com",
"phishing.example.com"
],
"createdAt": "2026-04-23T13:00:00.000Z",
"updatedAt": "2026-04-23T13:00:00.000Z"
}
Notes
nameis required and must be unique within the tenant.- A list can contain up to
100unique domain names. - A tenant can have up to
50custom domains lists.
List custom domains lists¶
Use this endpoint to retrieve custom domains lists, optionally filtered and sorted.
Request
GET /dns-protection/v2/custom-domains?page=1&pageSize=20&pageTotal=true
X-Tenant-ID: {tenantId}
Supported query parameters
Pagination
pagepageSizepageTotal
Filtering
name: exact custom domains list namenameContains: partial custom domains list name matchdomainNames: comma-separated list of exact domain names to match
Sorting
sort: one or more ofname,description,createdAt, orupdatedAt- Format:
fieldorfield:ascorfield:desc - Multiple fields are comma-separated, up to
4fields per request
Response
- Status:
200 OK
{
"pages": {
"current": 1,
"size": 20,
"total": 1,
"items": 2,
"maxSize": 200
},
"items": [
{
"id": "7a1ec1af-3b8d-47ad-bf91-ff05e9b94d28",
"name": "Allowed Sites",
"description": "Domains we always allow for office users",
"domains": [
"intranet.example.com",
"wiki.example.com"
],
"createdAt": "2026-04-23T12:45:00.000Z",
"updatedAt": "2026-04-23T12:45:00.000Z"
},
{
"id": "fe5d3f11-f8a5-45c3-b5be-48e0b66d15d2",
"name": "Blocked Sites",
"description": "Domains we always want to block for office users",
"domains": [
"malware.example.com",
"phishing.example.com"
],
"createdAt": "2026-04-23T13:00:00.000Z",
"updatedAt": "2026-04-23T13:00:00.000Z"
}
]
}
Filtering examples
Filter by exact name:
GET /dns-protection/v2/custom-domains?name=Blocked%20Sites
X-Tenant-ID: {tenantId}
Filter by partial name:
GET /dns-protection/v2/custom-domains?nameContains=Blocked
X-Tenant-ID: {tenantId}
Filter by exact domain names:
GET /dns-protection/v2/custom-domains?domainNames=malware.example.com,phishing.example.com
X-Tenant-ID: {tenantId}
Sort by name, then newest update first:
GET /dns-protection/v2/custom-domains?sort=name,updatedAt:desc
X-Tenant-ID: {tenantId}
Get custom domains list by ID¶
Use this endpoint to retrieve a single custom domains list.
Request
GET /dns-protection/v2/custom-domains/{id}
X-Tenant-ID: {tenantId}
Response
- Status:
200 OK
{
"id": "fe5d3f11-f8a5-45c3-b5be-48e0b66d15d2",
"name": "Blocked Sites",
"description": "Domains we always want to block for office users",
"domains": [
"malware.example.com",
"phishing.example.com"
],
"createdAt": "2026-04-23T13:00:00.000Z",
"updatedAt": "2026-04-23T13:00:00.000Z"
}
Update custom domains list¶
Use PATCH to update only the fields you want to change.
For domains, you can:
- send a full array to replace the existing values
- send an object with
addandremovefor partial changes - send
nullto clear the field
Request
PATCH /dns-protection/v2/custom-domains/{id}
X-Tenant-ID: {tenantId}
Content-Type: application/json
{
"description": "Updated block list for office users",
"domains": {
"add": ["spam.example.com"],
"remove": ["phishing.example.com"]
}
}
Response
- Status:
200 OK
{
"id": "fe5d3f11-f8a5-45c3-b5be-48e0b66d15d2",
"name": "Blocked Sites",
"description": "Updated block list for office users",
"domains": [
"malware.example.com",
"spam.example.com"
],
"createdAt": "2026-04-23T13:00:00.000Z",
"updatedAt": "2026-04-23T13:30:00.000Z"
}
Delete custom domains list¶
Use this endpoint to delete a custom domains list.
Request
DELETE /dns-protection/v2/custom-domains/{id}
X-Tenant-ID: {tenantId}
Response
- Status:
200 OK
{
"deleted": true
}
A custom domains list cannot be deleted while it is referenced by an existing policy. Remove the list ID from any allowedCustomDomainIds or blockedCustomDomainIds first, then delete the list.
Validation and behavior notes¶
The following rules are useful to know when building an integration:
Locations¶
- A tenant can have up to
50non-default locations in addition to the auto-provisioned default location. - Location names must be unique within a tenant and follow the pattern
^[a-zA-Z0-9\-_ ]+$, between 1 and 100 characters. - The combined number of
ipAddressesanddomainNameson a location cannot exceed100. - The default location is auto-provisioned for the tenant on first list of locations and cannot be deleted.
- The
typefield is case-sensitive and must be supplied in lowercase. Currently onlystandardis supported. - If a location is already in use by Endpoint Policy in a way that would break DNS Protection, the service rejects deletion and certain updates such as disabling DoH.
Policies¶
- A tenant can have up to
50policies. - Policy names must be unique within a tenant and follow the pattern
^[a-zA-Z0-9\-_ ]+$, between 1 and 100 characters. name,categoryGroupActionSettings,rejectedWebCategories, andlocationIdsare required when creating a policy.categoryGroupActionSettingsmust include all nine category-group keys (adult,social,threats,business,dataloss,bandwidth,productivity,uncategorized,infrastructure), and each value must be one ofallow,block, oralert.rejectedWebCategoriesonly accepts integer category IDs in the range1–110. Other values cause a400 Bad Request.- A location can belong to only one DNS Protection policy at a time. Trying to assign a location that is already owned by another policy results in a
409 Conflict. allowedCustomDomainIdsandblockedCustomDomainIdsmust not contain overlapping list IDs, and every ID must reference an existing custom domains list.locationIds,allowedCustomDomainIds,blockedCustomDomainIds, andrejectedWebCategorieseach support up to100items (andrejectedWebCategoriessupports up to500items inadd/removepatches).
Custom Domains Lists¶
- A tenant can have up to
50custom domains lists. - Custom domains list names must be unique within a tenant and follow the pattern
^[a-zA-Z0-9\-_ ]+$, between 1 and 100 characters. - A list can contain up to
100unique domain names; each domain must be a valid hostname. - A custom domains list cannot be deleted while it is referenced by a policy through
allowedCustomDomainIdsorblockedCustomDomainIds.
Response codes¶
| Code | Meaning |
|---|---|
200 | Successful read, update, or delete |
201 | Resource created successfully |
400 | Bad request or validation failure |
401 | Missing or invalid authentication |
403 | Forbidden |
404 | Resource not found |
409 | Conflict, for example duplicate names or invalid ownership/assignment |
500 | Unexpected server error |
Additional resources¶
For the generated API reference, see DNS Protection API reference.
You can also download a Postman collection for Sophos Fusion APIs.