Skip to content

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:

  1. Create or list the locations you want to manage.
  2. Optionally create one or more custom domains lists to allow or block specific domains.
  3. Create a policy that references the location IDs and any custom domains list IDs you want to apply.
  4. 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:

  • page is 1-based
  • page=0 returns page metadata only and no items
  • pageSize defaults to 20
  • the maximum supported pageSize is 200
  • pageTotal=true includes 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 allowedCustomDomainIds and blockedCustomDomainIds.
  • 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 policyId so you can see which policy currently owns it.

This means you typically use the APIs together:

  • Use /locations to create or discover the locations you want to protect.
  • Use /custom-domains to create the allow or block lists you want to apply.
  • Use /policies to 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 ipAddresses and domainNames must not exceed 100.
  • name is 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 standard location and set isDefault to true. Only one default location can exist per tenant.
  • If you omit type, the location is created as standard.

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 at 1
  • pageSize: number of items to return
  • pageTotal: whether to include total page and item counts

Filtering

  • name: exact location name
  • nameContains: partial location name match
  • isDefault: true or false (case-insensitive)
  • ipAddressesContains: comma-separated list of IP addresses; matches locations whose addresses contain any of the given values
  • domainNames: comma-separated list of exact domain names to match

Sorting

  • sort: one or more of name, description, or dohEnabled
  • Format: field or field:asc or field:desc
  • Multiple fields are comma-separated, up to 3 fields 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 add and remove for partial changes
  • send null to 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:

  • adult
  • social
  • threats
  • business
  • dataloss
  • bandwidth
  • productivity
  • uncategorized
  • infrastructure

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, and locationIds are required to create a policy.
  • categoryGroupActionSettings must include every category-group key listed above; omitting any of them causes a 400 Bad Request.
  • locationIds must reference existing DNS Protection locations, and a location can only belong to one policy at a time.
  • allowedCustomDomainIds and blockedCustomDomainIds must reference existing custom domains lists and must not contain overlapping IDs.
  • Each value in rejectedWebCategories must be an integer in the range 1–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

  • page
  • pageSize
  • pageTotal

Filtering

  • name: exact policy name
  • nameContains: partial policy name match
  • categoryPolicy: clean, optimal, bandwidth, business, or custom (case-insensitive)
  • safeSearchYouTubeRestrictionLevel: moderate or strict (case-insensitive)
  • safeSearchForSearchEnginesEnabled: true or false
  • safeSearchForYouTubeEnabled: true or false

Sorting

  • sort: one or more of name, description, categoryPolicy, createdAt, updatedAt
  • Format: field or field:asc or field:desc
  • Multiple fields are comma-separated, up to 5 fields 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 add and remove to update incrementally

This applies to:

  • locationIds
  • allowedCustomDomainIds
  • blockedCustomDomainIds
  • rejectedWebCategories

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 tenant
  • description: optional description
  • domains: set of domain names that belong to the list
  • id: 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

  • name is required and must be unique within the tenant.
  • A list can contain up to 100 unique domain names.
  • A tenant can have up to 50 custom 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

  • page
  • pageSize
  • pageTotal

Filtering

  • name: exact custom domains list name
  • nameContains: partial custom domains list name match
  • domainNames: comma-separated list of exact domain names to match

Sorting

  • sort: one or more of name, description, createdAt, or updatedAt
  • Format: field or field:asc or field:desc
  • Multiple fields are comma-separated, up to 4 fields 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 add and remove for partial changes
  • send null to 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 50 non-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 ipAddresses and domainNames on a location cannot exceed 100.
  • The default location is auto-provisioned for the tenant on first list of locations and cannot be deleted.
  • The type field is case-sensitive and must be supplied in lowercase. Currently only standard is 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 50 policies.
  • Policy names must be unique within a tenant and follow the pattern ^[a-zA-Z0-9\-_ ]+$, between 1 and 100 characters.
  • name, categoryGroupActionSettings, rejectedWebCategories, and locationIds are required when creating a policy.
  • categoryGroupActionSettings must include all nine category-group keys (adult, social, threats, business, dataloss, bandwidth, productivity, uncategorized, infrastructure), and each value must be one of allow, block, or alert.
  • rejectedWebCategories only accepts integer category IDs in the range 1–110. Other values cause a 400 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.
  • allowedCustomDomainIds and blockedCustomDomainIds must not contain overlapping list IDs, and every ID must reference an existing custom domains list.
  • locationIds, allowedCustomDomainIds, blockedCustomDomainIds, and rejectedWebCategories each support up to 100 items (and rejectedWebCategories supports up to 500 items in add / remove patches).

Custom Domains Lists

  • A tenant can have up to 50 custom 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 100 unique domain names; each domain must be a valid hostname.
  • A custom domains list cannot be deleted while it is referenced by a policy through allowedCustomDomainIds or blockedCustomDomainIds.

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.