Skip to main content

REST API overview

All administration and configuration of SafeDNS Shield is performed through the REST API. The API listens on port 8080 of the same IP address that handles DNS queries. By default, access is restricted to a set of whitelisted IP addresses specified during deployment.

Initial Configuration Example

The following example demonstrates the initial configuration workflow. Send the following request:

 
  • Type: POST
  • URL: <domain>/init/
  • Data:
{
    "profiles": [
        {
            "profile": {
                "id": 1,
                "page_id": 1
            },
            "cat_ids": [3, 4, 12],
            "app_ids": [1, 12, 93]
        }
    ],
    "blockpages": [
        {
            "id": 1,
            "type": 0
        },
        {
            "id": 2,
            "type": 1
        }
    ],
    "bw_lists": [
       {
            "profile_id": 1,
            "type": "deny",
            "domains": [
                "example1.com",
                "example2.com",
                "example3.com"
            ]
        }
    ],
    "nets": [
        {
            "ip": "100.100.100.100",
            "profile_id": 1,
            "prefix_len": 32
        },
        {
            "ip": "100.110.110.0",
            "profile_id": 1,
            "prefix_len": 24
        },
        {
            "ip": "100.120.0.0",
            "profile_id": 1,
            "prefix_len": 16
        }
    ],
    "nets6": [],
    "napts": []
}

The initialization query defines the full configuration applied to SafeDNS Shield. The following settings are processed in sequence:

  1. Filtering profile and block page – A filtering profile (ID=1) and a block page (ID=1) are created.

  2. Blocked categories – Three DNS categories are blocked for the profile: malware, phishing, and botnets.

  3. Blocked applications – Three AppBlocker categories are blocked: Slack, AnyDesk, and Netflix.

  4. Block pages – Two block pages of different types are created:

    • Type 0 – displays the blocked domain name.

    • Type 1 – does not display the blocked domain name.

  5. Blacklist – Three domains are added to the blacklist for filtering profile 1.

  6. IP assignment – The profile is assigned one specific IP address and two subnets (/16 and /24). DNS requests from these sources are filtered according to the profile’s policy.

  7. IPv6 and NAT‑port identification – The nets6 (IPv6) and napts (NAT port‑based identification) sections are included but left empty. These fields must be present in the request even if not used, to trigger the creation of the initial configuration.

Once the request is sent and a successful response (HTTP status 204) is received, the initial configuration is complete. All subsequent DNS traffic processed by the server is handled according to the specified rules.

Modifying Filtering Categories

To modify the filtering categories for an existing profile, you must update the entire list of categories assigned to that profile. Adding new categories requires sending the full set (both current and new categories) in a single request.

For example, the initial configuration created profile id=1 with three blocked categories: malware, phishing, and botnets. To add Cryptojacking, DGA, and Ransomware, the request must include all six categories:

 
  • Type: PATCH
  • URL: <domain>/profiles/1/
  • Data:
{
  "cat_ids": [3, 4, 12, 66, 70, 71],
  "app_ids": [1, 12, 93],
  "profile": {
    "page_id": 1
  }
}

In this request, the profile ID is specified directly in the URL. The request body contains the updated list of categories (original three and three new) while the AppBlocker categories and block page remain unchanged.

Adding a Domain to the Allowlist

To exempt a specific domain from category-based blocking, add it to the allowlist of the relevant filtering profile. For profile id=1, send the following request:

 
  • Type: POST
  • URL: <domain>/profile/1/bw_list
  • Data:
{
  "type": "allow",
  "domain": "example4.com"
}

This adds the domain to the allowlist, giving it priority over category-based blocking.

Adding Domains to the Denylist

To block specific domains that are not covered by the configured categories, add them directly to the denylist for the filtering profile. The following request adds domains in a batch operation for profile id=1:

 
  • Type: POST
  • URL: <domain>/profile/1/bw_list/batch
  • Data:
{
  "type": "deny",
  "domains": ["example5.com", "example6.com", "example7.com", "example8.com", "example9.com"]
}
Adding a Network or IP Address for Filtering

To assign a new IP address or subnet to a filtering profile, send the following request. The example adds a single IP address by specifying a /32 network prefix for profile id=1:

 
  • Type: POST
  • URL: <domain>/net/
  • Data:
{
    "ip": "100.100.100.101",
    "profile_id": 1,
    "prefix_len": 32
}

To add an entire subnet, adjust the prefix length accordingly. For instance, a /24 subnet would be specified as:

{
    "ip": "100.100.101.0",
    "profile_id": 1,
    "prefix_len": 24
}
Removing an IP Address from Filtering

To remove a previously assigned IP address or subnet from a filtering profile, send the following request:

  • Type: DELETE
  • URL: <domain>/net/1684300901
  • Data: None

This request has no body. The IP address must be provided in decimal format in the URL. Use the exact address originally submitted, without the mask - for example, 100.100.100.101 or 100.100.101.0 from the earlier examples. You can convert an IP address to decimal format using a tool like this one.

Modifying the Filtering Profile for a Specific IP

To change the filtering profile assigned to an existing IP address or subnet, send the following request. The IP address must be provided in decimal format in the URL. This example reassigns the address 100.100.101.0 (originally a /24 subnet) from profile id=1 to profile id=2:

 
  • Type: PATCH
  • URL: <domain>/net/1684301056
  • Data:
{
    "ip": "100.100.101.0",
    "profile_id": 2,
    "prefix_len": 24
}

To change the network prefix (for example, from /24 to /16), you must delete the existing record and add a new one with the correct network address. In this case, you would delete 100.100.101.0 and add 100.100.0.0 with the /16 prefix.

Creating a New Filtering Profile

Before an IP can be reassigned to a different profile, that profile must exist. The following request creates a new filtering profile:

 
  • Type: POST
  • URL: <domain>/profiles/
  • Data:


{ "profile": { "id": 2, "page_id": 1 }, "cat_ids": [3, 4, 12, 66, 70, 71, 13], "app_ids": [1, 12, 93] }

This creates profile id=2, configured with the same block page type and the same categories and AppBlocker settings as profile id=1, with the addition of the "Adult Related" category.

Complete API Methods Description

User data methods

 
    Initialize user data database (batch data creation):
      Type: POST
      URL: <domain>/init/
      Data:
      {
          'profiles': [
              {
                  'cat_ids': [<cat_id>,],
                  'app_ids': [<app_id>,],
                  'profile': {
                      'page_id': <page_id>,
                      'id': <id>
                  }
              }, ...
          ],
          'nets': [{'ip': <ipv4>, 'profile_id': <profile_id>, 'prefix_len': <prefix_len4>}, ...],
          'nets6': [{'ip': <ipv6>, 'profile_id': <profile_id>, 'prefix_len': <prefix_len6>}, ...],
          'blockpages': [{'id': <page_id>, 'type': <blockpage_type>}, ...],
          'napts': [
              {
                  'ip': <ipv4>,
                  "profile_id": <profile_id>,
                  "lower_port_bound": <lower_port_bound>,
                  "upper_port_bound": <upper_port_bound>
              },
          ]
      }
      Result: 204 No body

      Profile methods

       
        Fetch all profiles:
          Type: GET
          URL: <domain>/profiles
          Result: 200 OK Add a profile:
            Type: POST
            URL: <domain>/profiles
            Data:
            {
                "profile": {
                    "id": int,
                    "page_id": int
                },
                "cat_ids": [int, ],
                "app_ids": [int, ],
            }
            Result: 201 Created
              Fetch a specific profile:
                Type: GET
                URL: <domain>/profiles/<id>
                Result: 200 OK Update a specific profile:
                  Type: PATCH URL: <domain>/profiles Data:
                  {
                    "app_ids": [int, ],
                    "cat_ids": [int, ],
                    "profile": {
                      "plan_id": int,
                      "provider_id": int,
                      "white_list_only": bool,
                      "hide_block_reason": bool,
                      "empty_dns_answer": bool,
                      "page_id": int,
                      "tls": bool
                    }
                  }
                  Result: 200 OK

                  Blockpage methods

                   
                    Get all blockpages:
                      Type: GET
                      URL: <domain>/blockpage
                      Result: 200 OK Create a blockpage:
                        Type: POST
                        URL: <domain>/blockpage
                        Data:
                        {
                          "type": int,
                          "id": int
                        }
                        Result: 200 OK
                          Get a specific blockpage:
                            Type: GET
                            URL: <domain>/blockpage/<page_id> Result: 200 OK Update a blockpage:
                              Type: PATCH
                              URL: <domain>/blockpage/<page_id>
                              Data:
                              {
                                "type": int
                              }
                              Result: 200 OK
                                Delete a blockpage:
                                  Type: GET
                                  URL: <domain>/blockpage/<page_id> Result: 204 No Content, no body

                                  Lists methods

                                   
                                    Create an allow- or denylist:
                                      Type: POST URL: <domain>/profile/<profile_id>/bw_list Data:
                                      {
                                        "type": "string", //"allow" or "deny" only
                                        "domains": ["string", "string", ]
                                      }
                                      Result: 201 Created
                                        Create an allow- or denylist with multiple entries:
                                          Type: POST URL: <domain>/profile/<profile_id>/bw_list/batch Data:
                                          {
                                            "type": "string", //"allow" or "deny" only
                                            "domains": ["string", "string", ]
                                          }
                                          Result: 201 Created
                                            Update a domain in an allow- or denylist:
                                              Type: PATCH URL: <domain>/profile/<profile_id>/bw_list/<domain> Data:
                                              {
                                                "type": "string", //"allow" or "deny" only
                                                "domain": "string",
                                                "profile_id": int
                                              }
                                              Result: 200 OK
                                                Delete a domain from an allow- or denylist:
                                                  Type: DELETE URL: <domain>/profile/<profile_id>/bw_list/<domain> Result: 204 No Content, no body

                                                  IPv4 network methods

                                                   
                                                    Create an IPv4 address entry:
                                                      Type: POST
                                                      URL: <domain>/net
                                                      Data:
                                                      {
                                                        "ip": "string", //IPv4 address in canonical form
                                                        "profile_id": int,
                                                        "prefix_len": int
                                                      }
                                                      Result: 201 Created
                                                        Get an IPv4 address entry:
                                                          Type: GET
                                                          URL: <domain>/net/<int_ip>
                                                          Result: 200 OK Update an IPv4 address entry:
                                                            Type: PATCH
                                                            URL: <domain>/net/<int_ip>
                                                            Data:
                                                            {
                                                              "ip": "string", //IPv4 address in canonical form
                                                              "profile_id": int,
                                                              "prefix_len": int
                                                            }
                                                            Result: 200 OK
                                                              Delete an IPv4 address:
                                                                Type: DELETE
                                                                URL: <domain>/net/<int_ip>
                                                                Result: 204 No Content, no body

                                                                IPv6 network methods

                                                                 
                                                                  Create an IPv6 address entry:
                                                                    Type: POST
                                                                    URL: <domain>/net6
                                                                    Data:
                                                                    {
                                                                      "ip": "string", //IPv6 address in canonical form
                                                                      "prefix_len": int,
                                                                      "profile_id": int
                                                                    }
                                                                    Result: 201 Created
                                                                      Get an IPv6 address entry:
                                                                        Type: GET
                                                                        URL: <domain>/net6/<ipv6>
                                                                        Result: Dictionary with IPv6 and profile_id data Update an IPv6 address entry:
                                                                          Type: PATCH
                                                                          URL: <domain>/net6/<ipv6>
                                                                          Data:
                                                                          {
                                                                            "ip": "string", //IPv6 address in canonical form
                                                                            "prefix_len": int,
                                                                            "profile_id": int
                                                                          }
                                                                          Result: 200 OK
                                                                            Delete an IPv6 address:
                                                                              Type: DELETE
                                                                              URL: <domain>/net6/<ipv6>
                                                                              Result: 204 No Content, no body

                                                                              IPv4 NAT methods

                                                                               
                                                                                Create an IPv4 NAT entry:
                                                                                  Type: POST
                                                                                  URL: <domain>/napt/
                                                                                  Data:
                                                                                  {
                                                                                    "ip": "string", //IPv4 address in canonical form
                                                                                    "lower_port_bound": int,
                                                                                    "upper_port_bound": int,
                                                                                    "profile_id": int
                                                                                  }
                                                                                  Result: 201 Created
                                                                                    Create multiple IPv4 NAT entries:
                                                                                      Type: POST
                                                                                      URL: <domain>/napt/batch
                                                                                      Data:
                                                                                      [
                                                                                        {
                                                                                        	"ip": "string", //IPv4 address in canonical form
                                                                                        	"lower_port_bound": int,
                                                                                        	"upper_port_bound": int,
                                                                                        	"profile_id": int
                                                                                        },
                                                                                        
                                                                                      ]
                                                                                      Result: 201 Created
                                                                                        Get all IPv4 NAT entries by IP:
                                                                                          Type: GET
                                                                                          URL: <domain>/napt/<int_ip>
                                                                                          Result: 200 OK Get a specific IPv4 NAT entry:
                                                                                            Type: GET
                                                                                            URL: <domain>/napt/<int_ip>/<lower_port_bound>/<upper_port_bound>
                                                                                            Result: 200 OK Update an IPv4 NAT entry:
                                                                                              Type: PATCH
                                                                                              URL: <domain>/napt/<int_ip>/<lower_port_bound>/<upper_port_bound>
                                                                                              Data:
                                                                                              {
                                                                                                "ip": "string", //IPv4 address in canonical form
                                                                                                "lower_port_bound": int,
                                                                                                "upper_port_bound": int,
                                                                                                "profile_id": int
                                                                                              }
                                                                                              Result: 200 OK
                                                                                                Delete an IPv4 NAT entry:
                                                                                                  Type: DELETE
                                                                                                  URL: <domain>/napt/<int_ip>/<lower_port_bound>/<upper_port_bound>
                                                                                                  Result: 204 No Content, no body Delete multiple IPv4 NAT entries:
                                                                                                    Type: DELETE
                                                                                                    URL: <domain>/napt/batch
                                                                                                    Data:
                                                                                                    [
                                                                                                      {
                                                                                                      	"ip": "string", //IPv4 address in canonical form
                                                                                                      	"lower_port_bound": int,
                                                                                                      	"upper_port_bound": int,
                                                                                                      	"profile_id": int
                                                                                                      },
                                                                                                      
                                                                                                    ]
                                                                                                    Result: 204 No Content, no body

                                                                                                    AppBlocker methods

                                                                                                      Get a list of all available AppBlocker categories:
                                                                                                        Type: GET
                                                                                                        URL: <domain>/app_aware/application/
                                                                                                        Result: 200 OK